博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简单JNI使用demo
阅读量:6327 次
发布时间:2019-06-22

本文共 8707 字,大约阅读时间需要 29 分钟。

android中使用JNI的小例子,直接上代码。

首先是Java类JniClient,定义native方法,User实体类就不上代码了,就简单定义了三个属性,name、age、sex。

1 package com.example.ndkdemo; 2  3 public class JniClient { 4      5     /** 6      * 通过JNI简单输出字符串 7      * @return 8      */ 9     static public native String printStr();10     11     /**12      * 通过JNI简单进行整形加法操作13      * @param a14      * @param b15      * @return16      */17     static public native int addInt(int a, int b);18     19     /**20      * 通过JNI输入JAVA对象信息21      * @param user22      * @return23      */24     static public native String printUser(User user);25     26     /**27      * 通过JNI创建java对象28      * @param name29      * @param age30      * @param sex31      * @return32      */33     static public native User newUser(String name, int age, String sex);34     35     /**36      * 通过JNI调用无参构造函数创建java对象并且设置相应属性值37      * @param name38      * @param age39      * @param sex40      * @return41      */42     static public native User newUserNoArgs(String name, int age, String sex);43 }

 

然后使用cmd进入工程的classes目录通过javah命令生成c代码的头文件,命令:javah com.example.ndkdemo.JniClient ,这里生成的文件名字为:com_example_ndkdemo_JniClient.h

在工程下面新建一个jni目录,将生成的头文件拷贝到jni目录下面,创建com_example_ndkdemo_JniClient.c文件,在com_example_ndkdemo_JniClient.c文件里面实现各个native方法,代码如下:

1 #include "com_example_ndkdemo_JniClient.h"  2 #include 
3 #include
4 5 // 引入log头文件 6 #include
7 // log标签 8 #define TAG "jniCLient" 9 // 定义info信息 10 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) 11 // 定义debug信息 12 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) 13 // 定义error信息 14 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) 15 16 17 #ifdef __cplusplus 18 extern "C" 19 { 20 #endif 21 /* 22 * Class: com_example_ndkdemo_JniClient 23 * Method: printStr 24 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 25 */ 26 JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_JniClient_printStr 27 (JNIEnv *env, jclass arg) 28 { 29 jstring str = (*env)->NewStringUTF(env, "HelloWorld from JNI !"); 30 LOGI("log from jni"); 31 return str; 32 } 33 34 /* 35 * Class: com_example_ndkdemo_JniClient 36 * Method: AddInt 37 * Signature: (II)I 38 */ 39 JNIEXPORT jint JNICALL Java_com_example_ndkdemo_JniClient_addInt 40 (JNIEnv *env, jclass arg, jint a, jint b) 41 { 42 return a + b; 43 } 44 45 /** 46 * printUser 47 * jclass arg:因为方法为static,所以需要传入jclass参数,表明是哪个类的方法 48 */ 49 /** 50 *1)如果是C++代码,则用(*env),如果是C代码,则用env,否则报错: request for member 'GetObjectClass' in something not a structure or union 51 *2)所有方法都加了一个参数env,否则报错:too few arguments to function '(*env)->GetObjectClass' 52 *3)不能把.C文件改成.CPP文件,否则没有规则可以创建“out/apps/JNI_0529/armeabi/objs/JNI_0529/android_jni_MyJNINative.o”需要的目标“apps/JNI_0529/proje*ct/jni/android_jni_MyJNINative.c” 53 * 一个小例子错误真多啊!!NDK不简单啊!! 54 */ 55 JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_JniClient_printUser 56 (JNIEnv *env, jclass arg, jobject obj) 57 { 58 LOGI("add from jni--打印用户信息--"); 59 //获得obj对象的类 60 jclass cls_objClass = (*env)->GetObjectClass(env, obj); 61 /** 62 * 获得obj对象中特定方法getName的id 63 * env 64 * cls_objClass 方法所属类 65 * getName 方法名字 66 * ()Ljava/lang/String; 方法签名 67 */ 68 jmethodID nameMethodId = (*env)->GetMethodID(env, cls_objClass, "getName", "()Ljava/lang/String;"); 69 /** 70 * 调用obj对象的特定方法getName 71 * obj 调用方法的目标对象 72 * nameMethodId 调用方法的方法名 73 * ... 后面还可以添加方法需要的参数 74 */ 75 jstring js_name = (jstring)(*env)->CallObjectMethod(env, obj, nameMethodId); 76 //将jstring转为c中的字符数组 77 const char * name = (char *)(*env)->GetStringUTFChars(env, js_name, 0); 78 79 jmethodID ageMethodId = (*env)->GetMethodID(env, cls_objClass, "getAge", "()I"); 80 jint ji_age = (*env)->CallIntMethod(env, obj, ageMethodId); 81 82 jmethodID sexMethodId = (*env)->GetMethodID(env, cls_objClass, "getSex", "()Ljava/lang/String;"); 83 jstring js_sex = (jstring)(*env)->CallObjectMethod(env, obj, sexMethodId); 84 const char * sex = (char *)(*env)->GetStringUTFChars(env, js_sex, 0); 85 86 //打印信息 87 LOGI("user info----name:%s, age:%d, sex:%s.", name, ji_age, sex); 88 89 //释放资源 90 (*env)->ReleaseStringUTFChars(env, js_name, name); 91 (*env)->ReleaseStringUTFChars(env, js_sex, sex); 92 // printf("%s", str); 93 return js_name; 94 } 95 96 /** 97 * 创建一个对象(调用有参构造函数) 98 */ 99 JNIEXPORT jobject JNICALL Java_com_example_ndkdemo_JniClient_newUser100 (JNIEnv *env, jclass arg, jstring name, jint age, jstring sex)101 {102 //创建一个class的引用,使用类的全包名103 jclass cls = (*env)->FindClass(env, "com/example/ndkdemo/User");104 //注意这里方法的名称是"
",它表示这是一个构造函数105 jmethodID id = (*env)->GetMethodID(env, cls, "
", "(Ljava/lang/String;ILjava/lang/String;)V");106 //获得一实例,后面接构造函数参数107 // jobject obj = (*env)->NewObject(env, cls, id, name, age, sex);108 jstring jname = (*env)->NewStringUTF(env, "jni-liuling");109 jstring jsex = (*env)->NewStringUTF(env, "jni-男");110 jobject obj = (*env)->NewObject(env, cls, id, jname, 18L, jsex);111 112 return obj;113 }114 115 /**116 * 创建一个对象(调用无参构造函数)117 */118 JNIEXPORT jobject JNICALL Java_com_example_ndkdemo_JniClient_newUserNoArgs119 (JNIEnv *env, jclass arg, jstring name, jint age, jstring sex)120 {121 //创建一个class的引用,使用类的全包名122 jclass cls = (*env)->FindClass(env, "com/example/ndkdemo/User");123 //注意这里方法的名称是"
",它表示这是一个构造函数124 jmethodID id = (*env)->GetMethodID(env, cls, "
", "()V");125 //获得一实例,后面接构造函数参数126 jobject obj = (*env)->NewObject(env, cls, id);127 jstring jname = (*env)->NewStringUTF(env, "jni-liuling");128 jstring jsex = (*env)->NewStringUTF(env, "jni-男");129 130 //获取jfieldID131 jfieldID nameId = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");132 jfieldID ageId = (*env)->GetFieldID(env, cls, "age", "I");133 jfieldID sexId = (*env)->GetFieldID(env, cls, "sex", "Ljava/lang/String;");134 (*env)->SetObjectField(env, obj, nameId, jname);135 (*env)->SetIntField(env, obj, ageId, 18L);136 (*env)->SetObjectField(env, obj, sexId, jsex);137 138 return obj;139 }140 141 #ifdef __cplusplus142 }143 #endif

 

代码注释写的很详细,就不多讲了。

下面创建在jni目录下面创建编译文件Android.mk,内容如下:

1 LOCAL_PATH := $(call my-dir)2 include $(CLEAR_VARS)3 LOCAL_MODULE := NDKDemo4 LOCAL_SRC_FILES := com_example_ndkdemo_JniClient.c5 LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog6 include $(BUILD_SHARED_LIBRARY)

编译过程可以参考网上的,网上很多。下面是在android中调用的代码:

1 package com.example.ndkdemo; 2  3 import android.os.Bundle; 4 import android.support.v7.app.ActionBarActivity; 5 import android.util.Log; 6 import android.view.View; 7 import android.view.View.OnClickListener; 8 import android.widget.Button; 9 import android.widget.EditText;10 import android.widget.Toast;11 12 public class MainActivity extends ActionBarActivity {13 14     static {15         System.loadLibrary("NDKDemo");16     }17     18     @Override19     protected void onCreate(Bundle savedInstanceState) {20         super.onCreate(savedInstanceState);21         setContentView(R.layout.activity_main);22         findViewById(R.id.button).setOnClickListener(new OnClickListener() {23             @Override24             public void onClick(View v) {25                 //调用jni返回字符串26                 //Toast.makeText(MainActivity.this, JniClient.printStr(), Toast.LENGTH_LONG).show();27                 User user = new User("刘玲", 25, "男hahaah");28                 String name = JniClient.printUser(user);29                 Log.e("name", name + "");30 //                User user = JniClient.newUser("liuling", 18, "男");31 //                User user = JniClient.newUserNoArgs("liuling", 18, "男");32 //                Toast.makeText(MainActivity.this, user.toString(), Toast.LENGTH_LONG).show();33             }34         });35         final EditText num1 = (EditText) findViewById(R.id.num1);36         final EditText num2 = (EditText) findViewById(R.id.num2);37         final EditText result = (EditText) findViewById(R.id.result);38         Button addBtn = (Button) findViewById(R.id.addBtn);39         40         addBtn.setOnClickListener(new OnClickListener() {41             @Override42             public void onClick(View v) {43                 int n1 = Integer.valueOf(num1.getText().toString().trim());44                 int n2 = Integer.valueOf(num2.getText().toString().trim());45                 int n3 = JniClient.addInt(n1, n2);46                 result.setText(n3 + "");47             }48         });49         50     }51 52     53 }

这里要注意14-16行,一定要加载so文件。

 

转载地址:http://kkwoa.baihongyu.com/

你可能感兴趣的文章
WiFi安全那些事儿,整理推荐~
查看>>
Highcharts X轴纵向显示
查看>>
windows 注册表讲解
查看>>
【算法】论平衡二叉树(AVL)的正确种植方法
查看>>
35.angularJS的ng-repeat指令
查看>>
看不见的攻击面:查看 SQLite 数据库就中招?
查看>>
一些泛函分析题目
查看>>
基于DDD的现代ASP.NET开发框架--ABP系列之1、ABP总体介绍
查看>>
k8s 重要概念 - 每天5分钟玩转 Docker 容器技术(117)
查看>>
mysql优化-----多列索引的左前缀规则
查看>>
jQuery 中 is() 函数常见使用方法
查看>>
Smalltalk
查看>>
C# mongodb 类库
查看>>
系统调用(一)
查看>>
WCF 设计和实现服务协定(01)
查看>>
【原】东拼西凑PBR(1):PBR基础
查看>>
react 从零开始搭建开发环境
查看>>
scala recursive value x$5 needs type
查看>>
ps -ef |grep 输出的具体含义
查看>>
markdown编辑
查看>>