android的jni使用方法的一些探索和研究

发布时间:2016-12-6 13:57:16 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"android的jni使用方法的一些探索和研究",主要涉及到android的jni使用方法的一些探索和研究方面的内容,对于android的jni使用方法的一些探索和研究感兴趣的同学可以参考一下。

基础样例         这部分才是重点啊!多么切题。直接先看下运行的东西咯^^         是不是更有看的动力了?还是你拉到下边直接下载去了==。(没被鄙视简单吧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)TestJnipublic 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)AndroidNDKActivitypublic 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的方法:给出两个点的坐标,求它们的距离。首先,创建一个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/782787http://mobile.51cto.com/android-218239.htm

上一篇:Shell中的>/dev/null 2>&1 与 2>&1 >/dev/null 与&>/dev/null 的区别
下一篇:Java 使用JDBC、DBCP、C3P0访问数据库

相关文章

相关评论