你还在用ndk-build编so库,放弃吧,快来用cmake编译,cmake简直好用到不行,参考android JNI 开发之—cmake编译so库
本文会学习到一个简单的jni工程,类似于hello world,从最基础的概念到最后实现,中间会和大家一步一步学习,文章中参考的博文都是解决问题的方法,本人小白,如有错误,还请各位大佬指出,不胜感激。
实验环境:
工具:AS
包名:ryd.gyy.anative
JNI:
java本地接口(Java Native Interface),就是Java和C/C++相互通信的接口。
由于java执行效率比较低,而C/C++执行效率高,所以在AS中需要导入C/C++文件,jni就是连接java和C/C++之间的纽带。
NDK:
Native Develop Kit,在AS上用于C/C++开发的工具集。
Android NDK 是一套允许您使用C/C++实现部分应用的工具集。在开发某些类型应用时,这有助于您重复使用C/C++编写的代码库,也就是so库。
安装NDK:
第一次安装点击Download,安装成功之后如上图所示,NDK默认安装位置在SDK的路径下,可以在local.properties中查看。
NDK下载配置完成之后,需要在gradle.properties文件中加上一行(为了防止 so 库兼容错误):
android.useDeprecatedNdk=true
勾选上Include C++ support
项目会自动生成cpp文件和CMakeLists.txt
创建一个 JNITest.java 的一个类:
public class JNITest {
//创建一个 native 方法
public native static String get();
}
若创建完后出现如下问题,即get显示红色
进入setting—》Plugins—》NDK不打勾,重启AS即可
在AS控制台Terminal进入JNITest.java所在的目录执行
javac -encoding UTF-8 JNITest.java
正确生成后可以看到
-------------------------------------------我是分割线-----------------------------------------------
这里是我遇到的问题,没有问题的可以跳过。
问题一:执行javac出现下图
解决:首先确认下是否有配置好jdk的环境变量,在cmd输入javac,正确配置之后可以看到输出一大段命令详解。
笔者具体问题:AS没有配置jdk,配置之后可以在cmd看到命令详解,但是在AS控制台Terminal还是会出现上图内容,解决方法是重启电脑,之后就OK了。
问题二:使用javac JNITest.java来生成.class文件,出现下图内容
解决:使用javac -encoding UTF-8 Test.java来生成C/C++头文件
可以参考:错误:编码GBK的不可映射字符
-------------------------------------------我是分割线-----------------------------------------------
在AS的Terminal控制台上面回退目录到app/src/main,然后执行下面命令
javah -d jni -classpath ./java ryd.gyy.anative.JNITest
正确生成后可以看到
javah:生成h文件
-d:生成的.h的路径,这里是app/src/main
-classpath:用于装入类的路径,后面跟的是类
-jni:生成JNI样式的头文件,后面跟的是包名+类名
比较好理解的写法:javah -classpath 类的路径 -d 存放路径 -jni 包名+类名
大家可以参考这篇,讲的很详细Javah提示未找到 …的类文件
首先先把 setting—》Plugins—》NDK打勾,AS重启,这样才可以看到C/C++文件
在jni目录下创建一个C/C++ resource文件test.c,要选择C为后缀
#include<jni.h>
#include<stdio.h>
//导入我们创建的头文件
#include "ryd_gyy_anative_JNITest.h"
JNIEXPORT jstring JNICALL Java_ryd_gyy_anative_JNITest_get
(JNIEnv *env, jclass jclass){
//返回一个字符串
return (*env)->NewStringUTF(env,"This is my first NDK Application");
}
这个方法是我们从头文件中复制过来的(方法名、参数类型、返回值等必须一致!)
Android.mk文件:这里我是从其他地方直接复制过来然后修改的
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNITest
LOCAL_SRC_FILES := test.c
include $(BUILD_SHARED_LIBRARY)
LOCAL_MODULE:jni文件名
LOCAL_SRC_FILES:c++文件的名字
Application.mk文件:这里我是从其他地方直接复制过来然后修改的
APP_ABI := all
进入Settings–>Tools–>ExternalTools,点击+号增加
ndk -build命令,是根据C/C++文件生成so文件的:
E:\sdk\ndk-bundle\ndk-build.cmd 这里配置的是ndk下的ndk-build.cmd的路径(根据实际情况填写)
working directory按照图中的来添加,不变
使用方式:选中C/C++文件—>右键—>ExternalTools—>ndk-build,可以看到main文件夹下生成libs文件夹以及多个so文件,如上图所示。
在build.gradle文件夹的android{}下添加
sourceSets {
main() {
jniLibs.srcDirs = ['src/main/libs']//这是AS默认搜索库,
jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
}
}
这里可以参考这篇博客,马上就理解了 原来还有这种操作,libs和jniLibs 还有jni不得不说的关系
在JNITest.java中添加so库,这里写JNITest就可以了,这是lib库的规则。
package ryd.gyy.anative;
public class JNITest {
// 动态导入 so 库
static {
System.loadLibrary("JNITest");//这里写JNITest就可以了
}
//创建一个 native 方法
public native static String get();
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//打印信息
Log.e("Message",JNITest.get());
}
}
那么生成的so库,怎么让别人使用呢?请参考 android JNI 开发之—导入so库、jar并调用
啊~终于写完了,有问题评论区见。
作者:鸣人的修炼场
出处:https://blog.csdn.net/baidu_33693586
参考教程:
使用 Android Studio 写出第一个 NDK 程序(超详细)
Android studio 3.0 JNI开发生成so详细教程
NDK开发 从入门到放弃(一:基本流程入门了解)