NDK开发系列二
来源:互联网 发布:模架编程培训要多久 编辑:程序博客网 时间:2024/06/05 22:46
上一篇讲述了如何搭建环境以及解读第一个Demo,今天这篇将讲述如何创建自己的so库,并学习JNI中,Java如何调用C代码的。
一:创建native方法,并生成头文件
1:创建Java类
package com.luosiye.jni;/** * @author LuoSiYe * Created on 2017/12/14. * 新建一个Java类,并在方法前加上native关键词 * 这个时候会报错,没关系。 */public class JavaCallC { /** * 传入多个参数,返回结果,两个数相加 * */ public native int add(int arg0,int arg1); /** * 传入一个String类型,把C代码中的字符串进行拼接返回 * **/ public native String split(String arg0); /** * 给数组的每个元素都加上一个数字, * 并将数组元素返回 * **/ public native int[] addArray(int[] arg0); /** * 匹配密码,返回一个boolean类型的值 * **/ public native boolean checkPwd(String pwd);}
2:生成头文件
用javah -jni 命令的方式,看下图:
上面有些报错,可以不用管它,完成之后,我们就可以看到生成的头文件了。
二:编写.cpp代码
1:在cpp文件夹下创建文件,名称任意取
比如,我创建的文件叫luosiye.cpp,直接看代码,里面有很详尽的解释
#include <jni.h>#include <string>/** * extern "C" 一定记得把这句加上,不然就会找不到本地方法 * 关于方法名怎么写,可以直接在生成的那个头文件找到对应 * 的方法,拷贝过来,然后把参数补上 * **/extern "C"JNIEXPORT jint JNICALL Java_com_luosiye_jni_JavaCallC_add(JNIEnv * env, jobject object, jint arg0, jint arg1){ /** JNI 当中,基本数据类型,是可以相互任意转化的, * 比如,你也可以这样写, * int result = arg0+arg1 * return result * * 虽然arg0和arg1都是jint型,但是JNI规定基本数据类型可以相互转化 * */ return arg0 + arg1;}extern "C"JNIEXPORT jstring JNICALL Java_com_luosiye_jni_JavaCallC_split(JNIEnv * env, jobject object, jstring arg0){ /** * jstring 已经不属于基本数据类型了,所以需要先将jstring 转化成char* * **/ const char* fromJava = env->GetStringUTFChars(arg0,0); char* fromCplusplus = " and I am from Cplusplus"; char * result; //该方法是C++中string类的一个方法,需加上#include<string> sprintf(result,"%s%s",fromJava,fromCplusplus); //最后将两个拼接后的char* 重新转化成jstring类型 return env->NewStringUTF(result);}extern "C"JNIEXPORT jintArray JNICALL Java_com_luosiye_jni_JavaCallC_addArray(JNIEnv *env , jobject object, jintArray array){ //先获取数组的长度 int size = env->GetArrayLength(array); //获取该数组 jint* result = env->GetIntArrayElements(array,JNI_FALSE); //上面的两个方法,都可以在jni.h文件中找到, //对每个元素加10 for (int i = 0; i < size; ++i) { *(result+i) += 10; } return array;}extern "C"JNIEXPORT jboolean JNICALL Java_com_luosiye_jni_JavaCallC_checkPwd(JNIEnv *env , jobject object, jstring pwd){ char* sPwd = "123456"; //要先将jstring类型的pwd转换成char*, const char* uPwd = env->GetStringUTFChars(pwd,0); //比较两个字符串,strcmp()函数来自于string类 int result = strcmp(sPwd,uPwd); if (result ==0) return JNI_TRUE; else return JNI_FALSE;}
三:编译so文件
在CMakeLists.txt文件中添加你的so库文件,需要在两个地方添加内容,看下面的图:
add_library
link_library
添加完之后,我们Rebuild一下项目,然后去build/intermediates/cmake下面看有没有生成这个so文件,比如我的:
四:在Java代码中调用native方法
如果你前面的三步都问题,也把.so文件编译出来了,那么我们可以开始在Java代码中调用了。
1:首先,我们要在调用之前加上这行代码
static { System.loadLibrary("native-lib"); System.loadLibrary("luosiye-lib"); }
这个随便放在那,只要放在调用native方法前就行,另外,我们在build下生成的.so文件,AS通常会在前面加上一个lib,这个可以不用管,你要加载的lib名称,就是你在CMakeLists.txt配置的那个名称。
2:调用native方法
package com.luosiye.jni;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.Button;import android.widget.TextView;public class MainActivity extends AppCompatActivity { private final static String TAG = MainActivity.class.getSimpleName(); private TextView viewOne; private TextView viewTwo; private TextView viewThr; private Button clickBtn; private JavaCallC jni;//这个就是我们写native方法的类 static { System.loadLibrary("native-lib"); System.loadLibrary("luosiye-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); jni = new JavaCallC(); viewOne = findViewById(R.id.sample_text); viewTwo = findViewById(R.id.main_text_two); viewThr = findViewById(R.id.main_text_thr); clickBtn = findViewById(R.id.main_button); viewOne.setText(jni.add(99,1)+""); viewTwo.setText(jni.split("I am from java")); viewThr.setText("result == "+jni.checkPwd("123456")); int[] array = {1,2,3,4,5}; for (int i=0;i<5;i++){ Log.d(TAG,"第"+i+"个元素的返回值是:"+jni.addArray(array)[i]); } } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI();}
3:运行结果
Log
OK,今天这篇先说这些,下一篇将和大家讲述一下如何从C去调用Java代码。
阅读全文
0 0
- NDK开发系列二
- ndk 开发系列
- NDK开发系列一
- android ndk开发二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK 开发教程二
- 二---Android-NDK系列文章(1)
- Android-NDK开发之基础--Android NDK开发技巧二
- Android-NDK开发之基础--Android NDK开发技巧二
- ndk系列——使用Android Studio 初探NDK开发
- Android NDk开发系列(Hello JNI)
- Android NDk开发系列(疑难杂症篇)
- NDK开发系列之环境的搭建
- Android NDk开发系列之字符串操作
- otter系列—otter 基本介绍
- 740. Delete and Earn
- bzoj1041: [HAOI2008]圆上的整点
- Decorator函数
- 【Java学习笔记】父类引用指向子类对象之属性
- NDK开发系列二
- Hadoop读书笔记(一)——Hadoop分布式文件系统
- CS231n A2: Global name 'col2im_6d_cython' is not defined解决(Mac)
- python dict常用
- R语言UTF-8各种问题解决方法
- TypeError: data type "datetime" not understood
- canvas (1) 画一些简单的图形
- UDT的连接建立和释放
- 1加到100的和