android的jni使用方法的一些探索和研究
来源:互联网 发布:手机qq软件 编辑:程序博客网 时间:2024/04/25 01:53
基础样例
转自:
http://vaero.blog.51cto.com/4350852/782787
http://mobile.51cto.com/android-218239.htm
这部分才是重点啊!多么切题。直接先看下运行的东西咯^^
是不是更有看的动力了?还是你拉到下边直接下载去了==。(没被鄙视简单吧T^T)
1)C部分
1.1)TestJni.h
- /*
- * TestJni.h
- *
- * Created on: 2011-12-20
- * Author: Join
- */
- #ifndef TESTJNI_H_
- #define TESTJNI_H_
- #include <jni.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <android/log.h>
- #include <android/bitmap.h>
- // 测试回调Java
- #include "CallJava.h"
- #define LOG_TAG "JNI_DEBUG"
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
- // JNI调用函数必须要用C编译器编译
- // C++不加extern "C",调用会有异常
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * 说明:
- * 1、JNIEXPORT、JNICALL:jni的宏,在android的jni中不必须
- * 2、jstring:返回值类型(对应java的jni基本类型)
- * 3、C方法名:Java_pacakege_class_method
- * 4、JNIEnv*、jobject:jni必要参数(分别表示jni环境、java对象)
- */
- // 样例1:获取字符串
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv*,
- jobject);
- // 样例2:C回调Java静态及非静态方法
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv*,
- jobject, int, int, int, int);
- // 样例3:灰度化图像(Bitmap作为参数)(注:android-8才提供Bitmap.h)
- JNIEXPORT void JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv*,
- jobject, jobject);
- // 样例4:缺少JNIEXPORT、JNICALL测试
- jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv*, jobject);
- // 样例5:C方法不按规则命名尝试
- jint getInt(JNIEnv*, jobject);
- #ifdef __cplusplus
- }
- #endif
- // C++调用C
- //extern "C" {
- //#include "ImageUtil.h"
- //}
- //标准头文件为何有如下结构?
- //#ifdef __cplusplus
- //extern "C" {
- //#endif
- //...
- //#ifdef __cplusplus
- //}
- //#endif
- #endif /* TESTJNI_H_ */
1.2)TestJni.cpp
- /*
- * TestJni.cpp
- *
- * Created on: 2011-12-20
- * Author: Join
- */
- #include "TestJni.h"
- // 样例1:获取字符串
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv *env,
- jobject obj) {
- return env->NewStringUTF("I'm from C!");
- }
- int min(int x, int y) {
- return (x <= y) ? x : y;
- }
- // 样例2:C回调Java静态及非静态方法
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv *env,
- jobject obj, int add_x, int add_y, int sub_x, int sub_y) {
- char str[128]; // 字符数组
- int result_add = add(env, add_x, add_y); // 回调Java静态方法求和
- LOGE("==[%d+%d=%d]==", add_x, add_y, result_add);
- int result_sub = sub(env, sub_x, sub_y); // 回调Java非静态方法求差
- LOGE("==[%d-%d=%d]==", sub_x, sub_y, result_sub);
- // 将比较得的整数转成字符串
- sprintf(str, "Hello, I'm Join! min=%d", min(result_add, result_sub));
- return env->NewStringUTF(str);
- }
- typedef struct {
- uint8_t red;
- uint8_t green;
- uint8_t blue;
- uint8_t alpha;
- } argb;
- // 样例3:灰度化图像(Bitmap作为参数)(注:android-8才提供Bitmap.h)
- /**
- * bitmap:ARGB_8888,32位ARGB位图
- */
- JNIEXPORT void JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv * env,
- jobject obj, jobject bitmap) {
- AndroidBitmapInfo info;
- void* pixels;
- int ret;
- LOGI("convertToGray");
- if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
- LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
- return;
- }
- LOGI(
- "color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d", info.width, info.height, info.stride, info.format, info.flags);
- if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
- LOGE("Bitmap format is not RGBA_8888 !");
- return;
- }
- if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
- LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
- }
- // modify pixels with image processing algorithm
- int x, y;
- uint8_t gray;
- for (y = 0; y < info.height; y++) {
- argb * line = (argb *) pixels;
- for (x = 0; x < info.width; x++) {
- gray = 0.3 * line[x].red + 0.59 * line[x].green
- + 0.11 * line[x].blue;
- line[x].red = line[x].green = line[x].blue = gray;
- // line[x].alpha = 0xff; // 完全不透明
- }
- pixels = (char *) pixels + info.stride;
- }
- LOGI("unlocking pixels");
- AndroidBitmap_unlockPixels(env, bitmap);
- }
- // 样例4:缺少JNIEXPORT、JNICALL测试
- jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv *env, jobject obj) {
- int array[] = { 12, 34 }; // 新建一个int[]
- jintArray result = env->NewIntArray(2); // 新建一个jintArray
- env->SetIntArrayRegion(result, 0, 2, array); // 将int[]存入result
- return result;
- }
- // 样例5:C方法不按规则命名尝试
- jint getInt(JNIEnv *env, jobject obj) {
- return 256;
- }
1.3)回调相关
参照我的Java JNI简单实现一文,讲了些jni注意点的吧?
2)Java部分
2.1)TestJni
- public class TestJni {
- /** TAG标识 */
- private static final String TAG = "TestJni";
- /**
- * 载入动态库
- */
- static {
- System.loadLibrary("TestJni");
- }
- /** 样例1:获取字符串 */
- public static native String getStr();
- /** C回调Java方法(静态) */
- public static int add(int x, int y) {
- Log.e(TAG, "==Java静态add方法==");
- return x + y;
- }
- /** C回调Java方法(非静态) */
- public int sub(int x, int y) {
- Log.e(TAG, "==Java非静态sub方法==");
- return x - y;
- }
- /** 样例2:C回调Java静态及非静态方法 */
- public static native String callJava(int add_x, int add_y, int sub_x,
- int sub_y);
- /** 样例3:灰度化图像(Bitmap作为参数)(注:android-8才提供Bitmap.h) */
- public static native void convertToGray(Bitmap bitmap);
- /** 样例4:缺少JNIEXPORT、JNICALL测试 */
- public static native int[] getIntArray();
- /** 样例5:C方法不按规则命名尝试 */
- public static native int getInt();
- }
2.2)AndroidNDKActivity
- public class AndroidNDKActivity extends Activity implements
- View.OnClickListener {
- /** 标签 */
- private TextView text;
- /** 按钮 */
- private Button btn1, btn2, btn3, btn4, btn5;
- /** 图像 */
- private ImageView imageView;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- /* 初始化话各组件 */
- text = (TextView) findViewById(R.id.text);
- btn1 = (Button) findViewById(R.id.btn1);
- btn1.setOnClickListener(this);
- btn2 = (Button) findViewById(R.id.btn2);
- btn2.setOnClickListener(this);
- btn3 = (Button) findViewById(R.id.btn3);
- btn3.setOnClickListener(this);
- btn4 = (Button) findViewById(R.id.btn4);
- btn4.setOnClickListener(this);
- btn5 = (Button) findViewById(R.id.btn5);
- btn5.setOnClickListener(this);
- imageView = (ImageView) findViewById(R.id.imageView);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btn1:
- // 样例1:获取字符串
- text.setText(TestJni.getStr());
- break;
- case R.id.btn2:
- // 样例2:C回调Java静态及非静态方法
- text.setText(TestJni.callJava(2, 5, 8, 3));
- break;
- case R.id.btn3:
- // 获得Bitmap资源(32位)
- // BitmapFactory.Options options = new BitmapFactory.Options();
- // options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- // Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
- // R.drawable.ic_launcher, options);
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_launcher);
- // 样例3:灰度化图像(Bitmap作为参数)
- TestJni.convertToGray(bitmap);
- imageView.setImageBitmap(bitmap);
- break;
- case R.id.btn4:
- // 样例4:缺少JNIEXPORT、JNICALL测试
- int[] array = TestJni.getIntArray();
- int len = array.length;
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < len - 1; i++) {
- sb.append(array[i]);
- sb.append(",");
- }
- sb.append(array[len - 1]);
- text.setText(sb.toString());
- break;
- case R.id.btn5:
- // 样例5:C方法不按规则命名尝试
- try {
- int value = TestJni.getInt();
- text.setText(String.valueOf(value));
- } catch (UnsatisfiedLinkError e) {
- text.setText("UnsatisfiedLinkError!");
- e.printStackTrace();
- }
- break;
- }
- }
- }
三、后记
也是整理的基础样例工程,嘿嘿!
注意:
1)需要2.2系统才可,用了Bitmap.h。
2)样例5(不按命名规则的那个),用jni对方法进行注册,不按要求写方法名也是可以的。
3)灰度化是用的标准公式:Gray = R*0.299 + G*0.587 + B*0.114(考虑效率的话,有移位公式)
4)在android-ndk-r6\platforms\android-8\arch-arm\usr\lib目录下是NDK提供的可调用库。(有OpenGL ES^^)
另一个实例,jni调用java的方法:
另一个实例,jni调用java的方法:
给出两个点的坐标,求它们的距离。
首先,创建一个Point对象,
Java代码
- public class Point {
- float x;
- float y;
- }
然后在c文件中定义一个函数
C代码
- jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b){}
返回值是float,在jni中定义的是jfloat。
函数名规则: Java开头,接着是包名的每一段,然后是类名,最后是Java中调用的方法名,中间都用下划线隔开。第一个参数JNIEnv* env和第二个参数jobject thiz都是必须的,后面的才是Java中传递进来的参数。这里是两个Point对象。
首先确定要做的步骤:
◆找到这个Point类
◆找到类中的域x和y的域id
◆根据ID取出x和y的值
◆计算结果并返回
那么代码如下:
Java代码
- #include <jni.h>
- #include <math.h>
- #include <android/log.h>
- jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b)
- {
- //步骤1
- jclass point_class = (*env)->FindClass(env, "chroya/demo/ndk/Point");
- if(point_class == NULL) {
- //printf("class not found");
- __android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "class Point not found");
- return 0;
- } else {
- __android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "found class Point");
- }
- //步骤2
- jfieldID field_x = (*env)->GetFieldID(env, point_class, "x", "F");
- jfieldID field_y = (*env)->GetFieldID(env, point_class, "y", "F");
- //步骤3
- jfloat ax = (*env)->GetFloatField(env, a, field_x);
- jfloat ay = (*env)->GetFloatField(env, a, field_y);
- jfloat bx = (*env)->GetFloatField(env, b, field_x);
- jfloat by = (*env)->GetFloatField(env, b, field_y);
- //步骤4
- return sqrtf(powf(bx-ax, 2) + powf(by-ay, 2));
- }
然后在Java里面调用:
Java代码
- public class Main extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- TextView tv = new TextView(getApplicationContext());
- Point a = new Point();
- a.x = 3;
- a.y = 3;
- Point b = new Point();
- b.x = 5;
- b.y = 5;
- float d = distance(a,b);
- tv.setText("distance(a,b):"+d);
- setContentView(tv);
- }
- public native float distance(Point a, Point b);
- static {
- System.loadLibrary("demo");
- }
- }
转自:
http://vaero.blog.51cto.com/4350852/782787
http://mobile.51cto.com/android-218239.htm
- android的jni使用方法的一些探索和研究
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Android中JNI的使用方法
- Linux互斥锁的使用代码实现
- 创建文件夹问题
- Asp 导出Excel
- Shell中的>/dev/null 2>&1 与 2>&1 >/dev/null 与&>/dev/null 的区别
- 找工作笔试面试补充基础知识(1)---内存对齐
- android的jni使用方法的一些探索和研究
- 页面置换算法
- 百度与谷歌搜索结果差异
- 【推荐】JAVA基础◆浅谈3DES加密解密
- 【学习笔记】【Cocos2d-x Lua脚本开发】如何使用Lua脚本调用自定义类
- 全新讴歌RLX 不做孤独的隐形人
- js 获取浏览器高度和宽度值(多浏览器)
- 关于hibernate查询sqlserver时char类型只能取第一个字符的问题
- YUV420转YUV444 , YUV420转RGB