android ndk开发(二)实现一个官方demo
实现了一个官方的demo:bitmap-plasma(水波纹)
源代码就在samples文件夹下,可以自己去找。
界面:
建立项目的步骤和配置环境不明白的可以去看:http://www.cnblogs.com/jycboy/p/5393727.html
一、activity代码:
package example.user.plasmatest; import android.os.Bundle;
import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.view.View;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.Display;
import android.view.WindowManager; public class MainActivity extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Display display = getWindowManager().getDefaultDisplay();
setContentView(new PlasmaView(this, display.getWidth(), display.getHeight()));
} /* load our native library */
static {
System.loadLibrary("plasma");
}
} class PlasmaView extends View {
private Bitmap mBitmap;
private long mStartTime; /* implementend by libplasma.so */
private static native void renderPlasma(Bitmap bitmap, long time_ms); public PlasmaView(Context context, int width, int height) {
super(context);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
mStartTime = System.currentTimeMillis();
} @Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xFFCCCCCC);
renderPlasma(mBitmap, System.currentTimeMillis() - mStartTime);
canvas.drawBitmap(mBitmap, 0, 0, null);
// force a redraw, with a different time-based pattern.
invalidate();
}
}
make project下,利用javah创建jni目录、.h头文件
在jni目录下创建c代码:
plasma.c:
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "example_user_plasmatest_PlasmaView.h"
#include <jni.h>
#include <time.h>
#include <android/log.h>
#include <android/bitmap.h> #include <stdio.h>
#include <stdlib.h>
#include <math.h> #define LOG_TAG "libplasma"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) /* Set to 1 to enable debug log traces. */
#define DEBUG 0 /* Set to 1 to optimize memory stores when generating plasma. */
#define OPTIMIZE_WRITES 1 /* Return current time in milliseconds */
static double now_ms(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*. + tv.tv_usec/.;
} /* We're going to perform computations for every pixel of the target
* bitmap. floating-point operations are very slow on ARMv5, and not
* too bad on ARMv7 with the exception of trigonometric functions.
*
* For better performance on all platforms, we're going to use fixed-point
* arithmetic and all kinds of tricks
*/ typedef int32_t Fixed; #define FIXED_BITS 16
#define FIXED_ONE (1 << FIXED_BITS)
#define FIXED_AVERAGE(x,y) (((x) + (y)) >> 1) #define FIXED_FROM_INT(x) ((x) << FIXED_BITS)
#define FIXED_TO_INT(x) ((x) >> FIXED_BITS) #define FIXED_FROM_FLOAT(x) ((Fixed)((x)*FIXED_ONE))
#define FIXED_TO_FLOAT(x) ((x)/(1.*FIXED_ONE)) #define FIXED_MUL(x,y) (((int64_t)(x) * (y)) >> FIXED_BITS)
#define FIXED_DIV(x,y) (((int64_t)(x) * FIXED_ONE) / (y)) #define FIXED_DIV2(x) ((x) >> 1)
#define FIXED_AVERAGE(x,y) (((x) + (y)) >> 1) #define FIXED_FRAC(x) ((x) & ((1 << FIXED_BITS)-1))
#define FIXED_TRUNC(x) ((x) & ~((1 << FIXED_BITS)-1)) #define FIXED_FROM_INT_FLOAT(x,f) (Fixed)((x)*(FIXED_ONE*(f))) typedef int32_t Angle; #define ANGLE_BITS 9 #if ANGLE_BITS < 8
# error ANGLE_BITS must be at least
#endif #define ANGLE_2PI (1 << ANGLE_BITS)
#define ANGLE_PI (1 << (ANGLE_BITS-1))
#define ANGLE_PI2 (1 << (ANGLE_BITS-2))
#define ANGLE_PI4 (1 << (ANGLE_BITS-3)) #define ANGLE_FROM_FLOAT(x) (Angle)((x)*ANGLE_PI/M_PI)
#define ANGLE_TO_FLOAT(x) ((x)*M_PI/ANGLE_PI) #if ANGLE_BITS <= FIXED_BITS
# define ANGLE_FROM_FIXED(x) (Angle)((x) >> (FIXED_BITS - ANGLE_BITS))
# define ANGLE_TO_FIXED(x) (Fixed)((x) << (FIXED_BITS - ANGLE_BITS))
#else
# define ANGLE_FROM_FIXED(x) (Angle)((x) << (ANGLE_BITS - FIXED_BITS))
# define ANGLE_TO_FIXED(x) (Fixed)((x) >> (ANGLE_BITS - FIXED_BITS))
#endif static Fixed angle_sin_tab[ANGLE_2PI+]; static void init_angles(void)
{
int nn;
for (nn = ; nn < ANGLE_2PI+; nn++) {
double radians = nn*M_PI/ANGLE_PI;
angle_sin_tab[nn] = FIXED_FROM_FLOAT(sin(radians));
}
} static __inline__ Fixed angle_sin( Angle a )
{
return angle_sin_tab[(uint32_t)a & (ANGLE_2PI-)];
} static __inline__ Fixed angle_cos( Angle a )
{
return angle_sin(a + ANGLE_PI2);
} static __inline__ Fixed fixed_sin( Fixed f )
{
return angle_sin(ANGLE_FROM_FIXED(f));
} static __inline__ Fixed fixed_cos( Fixed f )
{
return angle_cos(ANGLE_FROM_FIXED(f));
} /* Color palette used for rendering the plasma */
#define PALETTE_BITS 8
#define PALETTE_SIZE (1 << PALETTE_BITS) #if PALETTE_BITS > FIXED_BITS
# error PALETTE_BITS must be smaller than FIXED_BITS
#endif static uint16_t palette[PALETTE_SIZE]; static uint16_t make565(int red, int green, int blue)
{
return (uint16_t)( ((red << ) & 0xf800) |
((green << ) & 0x03e0) |
((blue >> ) & 0x001f) );
} static void init_palette(void)
{
int nn, mm = ;
/* fun with colors */
for (nn = ; nn < PALETTE_SIZE/; nn++) {
int jj = (nn-mm)**/PALETTE_SIZE;
palette[nn] = make565(, jj, -jj);
} for ( mm = nn; nn < PALETTE_SIZE/; nn++ ) {
int jj = (nn-mm)**/PALETTE_SIZE;
palette[nn] = make565(-jj, , jj);
} for ( mm = nn; nn < PALETTE_SIZE*/; nn++ ) {
int jj = (nn-mm)**/PALETTE_SIZE;
palette[nn] = make565(, -jj, );
} for ( mm = nn; nn < PALETTE_SIZE; nn++ ) {
int jj = (nn-mm)**/PALETTE_SIZE;
palette[nn] = make565(jj, , );
}
} static __inline__ uint16_t palette_from_fixed( Fixed x )
{
if (x < ) x = -x;
if (x >= FIXED_ONE) x = FIXED_ONE-;
int idx = FIXED_FRAC(x) >> (FIXED_BITS - PALETTE_BITS);
return palette[idx & (PALETTE_SIZE-)];
} /* Angles expressed as fixed point radians */ static void init_tables(void)
{
init_palette();
init_angles();
} static void fill_plasma( AndroidBitmapInfo* info, void* pixels, double t )
{
Fixed yt1 = FIXED_FROM_FLOAT(t/.);
Fixed yt2 = yt1;
Fixed xt10 = FIXED_FROM_FLOAT(t/.);
Fixed xt20 = xt10; #define YT1_INCR FIXED_FROM_FLOAT(1/100.)
#define YT2_INCR FIXED_FROM_FLOAT(1/163.) int yy;
for (yy = ; yy < info->height; yy++) {
uint16_t* line = (uint16_t*)pixels;
Fixed base = fixed_sin(yt1) + fixed_sin(yt2);
Fixed xt1 = xt10;
Fixed xt2 = xt20; yt1 += YT1_INCR;
yt2 += YT2_INCR; #define XT1_INCR FIXED_FROM_FLOAT(1/173.)
#define XT2_INCR FIXED_FROM_FLOAT(1/242.) #if OPTIMIZE_WRITES
/* optimize memory writes by generating one aligned 32-bit store
* for every pair of pixels.
*/
uint16_t* line_end = line + info->width; if (line < line_end) {
if (((uint32_t)(uintptr_t)line & ) != ) {
Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2); xt1 += XT1_INCR;
xt2 += XT2_INCR; line[] = palette_from_fixed(ii >> );
line++;
} while (line + <= line_end) {
Fixed i1 = base + fixed_sin(xt1) + fixed_sin(xt2);
xt1 += XT1_INCR;
xt2 += XT2_INCR; Fixed i2 = base + fixed_sin(xt1) + fixed_sin(xt2);
xt1 += XT1_INCR;
xt2 += XT2_INCR; uint32_t pixel = ((uint32_t)palette_from_fixed(i1 >> ) << ) |
(uint32_t)palette_from_fixed(i2 >> ); ((uint32_t*)line)[] = pixel;
line += ;
} if (line < line_end) {
Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2);
line[] = palette_from_fixed(ii >> );
line++;
}
}
#else /* !OPTIMIZE_WRITES */
int xx;
for (xx = ; xx < info->width; xx++) { Fixed ii = base + fixed_sin(xt1) + fixed_sin(xt2); xt1 += XT1_INCR;
xt2 += XT2_INCR; line[xx] = palette_from_fixed(ii / );
}
#endif /* !OPTIMIZE_WRITES */ // go to next line
pixels = (char*)pixels + info->stride;
}
} /* simple stats management */
typedef struct {
double renderTime;
double frameTime;
} FrameStats; #define MAX_FRAME_STATS 200
#define MAX_PERIOD_MS 1500 typedef struct {
double firstTime;
double lastTime;
double frameTime; int firstFrame;
int numFrames;
FrameStats frames[ MAX_FRAME_STATS ];
} Stats; static void
stats_init( Stats* s )
{
s->lastTime = now_ms();
s->firstTime = .;
s->firstFrame = ;
s->numFrames = ;
} static void
stats_startFrame( Stats* s )
{
s->frameTime = now_ms();
} static void
stats_endFrame( Stats* s )
{
double now = now_ms();
double renderTime = now - s->frameTime;
double frameTime = now - s->lastTime;
int nn; if (now - s->firstTime >= MAX_PERIOD_MS) {
if (s->numFrames > ) {
double minRender, maxRender, avgRender;
double minFrame, maxFrame, avgFrame;
int count; nn = s->firstFrame;
minRender = maxRender = avgRender = s->frames[nn].renderTime;
minFrame = maxFrame = avgFrame = s->frames[nn].frameTime;
for (count = s->numFrames; count > ; count-- ) {
nn += ;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS;
double render = s->frames[nn].renderTime;
if (render < minRender) minRender = render;
if (render > maxRender) maxRender = render;
double frame = s->frames[nn].frameTime;
if (frame < minFrame) minFrame = frame;
if (frame > maxFrame) maxFrame = frame;
avgRender += render;
avgFrame += frame;
}
avgRender /= s->numFrames;
avgFrame /= s->numFrames; LOGI("frame/s (avg,min,max) = (%.1f,%.1f,%.1f) "
"render time ms (avg,min,max) = (%.1f,%.1f,%.1f)\n",
./avgFrame, ./maxFrame, ./minFrame,
avgRender, minRender, maxRender);
}
s->numFrames = ;
s->firstFrame = ;
s->firstTime = now;
} nn = s->firstFrame + s->numFrames;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS; s->frames[nn].renderTime = renderTime;
s->frames[nn].frameTime = frameTime; if (s->numFrames < MAX_FRAME_STATS) {
s->numFrames += ;
} else {
s->firstFrame += ;
if (s->firstFrame >= MAX_FRAME_STATS)
s->firstFrame -= MAX_FRAME_STATS;
} s->lastTime = now;
} JNIEXPORT void JNICALL Java_example_user_plasmatest_PlasmaView_renderPlasma(JNIEnv * env, jobject obj, jobject bitmap, jlong time_ms)
{
AndroidBitmapInfo info;
void* pixels;
int ret;
static Stats stats;
static int init; if (!init) {
init_tables();
stats_init(&stats);
init = ;
} if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < ) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
} if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {
LOGE("Bitmap format is not RGB_565 !");
return;
} if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < ) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
} stats_startFrame(&stats); /* Now fill the values with a nice little plasma */
fill_plasma(&info, pixels, time_ms ); AndroidBitmap_unlockPixels(env, bitmap); stats_endFrame(&stats);
}
//
// Created by user on 2016/4/14.
//
修改build.gradle文件: 添加ndk{......}
defaultConfig {
applicationId "example.user.plasmatest"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk{
moduleName "plasma"
ldLibs "log"
ldLibs "jnigraphics"//新增
}
}
修改Android.mk文件:
添加:LOCAL_LDLIBS := -llog -ljnigraphics
这是我的Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE := plasma
LOCAL_LDFLAGS := -Wl,--build-id
LOCAL_LDLIBS := \
-llog \
-ljnigraphics \ LOCAL_SRC_FILES := \
D:\as_workspace\NDKDemo2\plasmatest\src\main\jni\plasma.c \
D:\as_workspace\NDKDemo2\plasmatest\src\main\jni\util.c \ LOCAL_C_INCLUDES += D:\as_workspace\NDKDemo2\plasmatest\src\main\jni
LOCAL_C_INCLUDES += D:\as_workspace\NDKDemo2\plasmatest\src\debug\jni include $(BUILD_SHARED_LIBRARY)
运行即可。。。
遇到的问题:
问题一:Error:(383) undefined reference to `__android_log_print':
1 修改 Android.mk 文件相关:
1 |
LOCAL_LDLIBS := -llog |
2 如果使用 android studio,需要修改 gradle 脚本:
1 |
android { |
也就是添加了一句:ldLibs "log"
问题二:Error:(377) undefined reference to `AndroidBitmap_getInfo'
修改Android.mk文件:
添加:LOCAL_LDLIBS := -llog -ljnigraphics
修改 gradle 脚本如下:
ndk {
moduleName "webcam"
ldLibs "log"
ldLibs "jnigraphics"
}
其实这句的意思就是增加动态链接库 jnigraphics
,这样就搞定了呢,是的,就是这样。
问题三:找不到appcompatActivity
这时候你的activity应该继承的是appcompatActivity,
解决方法一:修改成继承Activity就可以
解决方法二:javah -d jni -classpath D:\ide\android-sdk\platforms\android-22\android.jar;D:\ide\android-sdk\extras\android\support\v7\appcompat\libs\android-support-v7-appcompat.jar;..\..\build\intermediates\classes\debug
在javah命令中加上android-support-v7-appcompat.jar这个的路径,在安装目录下,一级级找就可以。
几个很好的学习ndk的博客:
JNI官方规范中文版:http://blog.csdn.net/a345017062/article/category/1256568
Android 开发之 JNI入门 - NDK从入门到精通(说的很全):http://www.hanshuliang.com/?post=3
http://blog.csdn.net/shulianghan/article/details/18964835(推荐)
NDK开发:http://blog.csdn.net/conowen/article/category/1127720
JNI实战:http://blog.csdn.net/yanbober/article/details/45309049(推荐)
极客学院的:http://wiki.jikexueyuan.com/project/jni-ndk-developer-guide/overview.html(推荐)
android ndk开发(二)实现一个官方demo的更多相关文章
- Android NDK 开发(二) -- 从Hlello World学起【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41805719 上篇文章讲述了Android NDK开发的一些基本概念,以及NDK ...
- Android NDK开发初识
神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...
- Android NDK开发
Android NDK 开发教程(极客学院) 一.Android NDK环境搭建 使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin( ...
- Android NDK开发Hello Word!
在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...
- !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-opencv-development-3/ Android Ndk a ...
- android NDK开发在本地C/C++源码中设置断点单步调试具体教程
近期在学android NDK开发,折腾了一天,最终可以成功在ADT中设置断点单步调试本地C/C++源码了.网上关于这方面的资料太少了,并且大都不全,并且调试过程中会出现各种各样的问题,真是非常磨人. ...
- windows下用ADT进行android NDK开发的具体教程(从环境搭建、配置到编译全过程)
郑重申明:如需转载本博客,请注明出处,谢谢! 这几天在学习android NDK的开发.那么首先让我们来看看android NDK开发的本质是什么. NDK(Native Development Ki ...
- Android NDK 开发(四)java传递数据到C【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处 ...
- Android NDK 开发(三)--常见错误锦集合Log的使用【转】
转载请注明出处:http://blog.csdn.net/allen315410/article/details/41826511 Android NDK开发经常因某些因素会出现一些意想不到的错误, ...
- android NDK开发环境搭建
android NDK开发环境搭建 2012-05-14 00:13:58 分类: 嵌入式 基于 Android NDK 的学习之旅-----环境搭建 工欲善其事必先利其器 , 下面介绍下 Eclip ...
随机推荐
- java类加载器-前序
前序 前几天,一个人经常在QQ群里问一些java热更新的知识.后来他实现了热更新,但是还是遇到各种问题.我给他做了解答,并看了下他写的类加载器,他的实现大概是这样子的: (问我此问题的网友,如果你看到 ...
- CSS魔法堂:你一定误解过的Normal flow
前言 刚接触CSS时经常听到看到一个词"文档流",那到底什么是"文档流"呢?然后会看到"绝对定位和浮动定位能脱离文档流",从这句可以看到文 ...
- 音频文件解析(二):WAV格式文件波形绘制
解析WAV头部信息后,接下来就可以根据相关参数和DATA块数据绘制波形. 1.重新编码(转换为8bits,单声道数据) Public Function GetFormatData(ByVal pDat ...
- max server memory
MS SQL Server 2008 R2,主要是用作ERP的数据库,但它的内存使用率非常高: 经查资料,原来数据库有默认的情况之下,使用内存时它是尽可能使用完有效内存.如果你不想这样,你可以手动分配 ...
- C#编程总结(四)多线程应用
C#编程总结(四)多线程应用 多线程应用很广泛,简单总结了一下: 1)不阻断主线程,实现即时响应,由后台线程完成特定操作2)多个线程,完成同类任务,提高并发性能3)一个任务有多个独立的步骤,多个线程并 ...
- C#的变迁史 - C# 4.0篇
C# 4.0 (.NET 4.0, VS2010) 第四代C#借鉴了动态语言的特性,搞出了动态语言运行时,真的是全面向“高大上”靠齐啊. 1. DLR动态语言运行时 C#作为静态语言,它需要编译以后运 ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析(五)ReservedPacketType
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是 ...
- Web API:将FlexChart导出为图片
如果想要将FlexChart在应用之外使用,比如使用在报表中,Web API帮助你将FlexChart导出成任何你需要的图片格式. 下面是实现的步骤: 1:创建FlexChart 2:调用Servic ...
- Android Volley框架的使用(1)
在Android开发中,经常要通过HTTP请求访问网络.为了使通过HTTP请求访问网络的过程更加简单,2013年提出了新的HTTP通信框架--Volley.Volley使用起来非常简单,适用于网络访问 ...
- Using Recursive Common table expressions to represent Tree structures
http://www.postgresonline.com/journal/archives/131-Using-Recursive-Common-table-expressions-to-repre ...