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

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

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();1011     /12       通过JNI简单进行整形加法操作13       @param a14       @param b15       @return16      /17     static public native int addInt(int a, int b);1819     /**20       通过JNI输入JAVA对象信息21       @param user22       @return23      /24     static public native String printUser(User user);2526     /**27       通过JNI创建java对象28       @param name29       @param age30       @param sex31       @return32      /33     static public native User newUser(String name, int age, String sex);3435     /**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/project/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);111112     return obj;113 }114115 /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-男“);129130     //获取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);137138     return obj;139 }140141 #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;1112 public class MainActivity extends ActionBarActivity {1314     static {15         System.loadLibrary(“NDKDemo”);16     }1718     @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);3940         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         });4950     }515253 }

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

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

你可能感兴趣的文章
【iCore3 双核心板_FPGA】例程十三:FSMC总线通信实验——复用地址模式
查看>>
onethink加密解密函数
查看>>
重写 Ext.toolbar.Paging 扩展功能
查看>>
冒泡排序
查看>>
linux进程地址空间--vma的基本操作【转】
查看>>
李洪强iOS开发之提交AppStory时候遇到的坑
查看>>
maven 跳过测试 打包 及上传命令
查看>>
Git安装与配置
查看>>
JavDroider的作品展示
查看>>
Eziriz .NET Reactor(.net混淆器) v5.0.0.0 完美安装破解版(附破解文件)
查看>>
Python3 写Windows Service服务程序
查看>>
strncpy, strncpy_s
查看>>
sqlserver 大杂烩
查看>>
python俱乐部
查看>>
haXe
查看>>
python --Everything is Object
查看>>
解决问题的方式
查看>>
Haffman编码(haffman树)
查看>>
Java排序算法——插入排序
查看>>
Swift3.0语言教程使用路径字符串
查看>>