Jni是android提供的与其他语言交互的接口,常用的就是c或c++,之前写jni代码是非常痛苦的,一方面像写记事本一样没有各种函数提示,一方面无法调试,单靠打log效率非常低,所以之前都有点不想写jni的代码,但是最近得知了jni可以像Java一样动态调试,非常感兴趣,经过一番折腾,把具体步骤介绍一下。
一、前提条件
1、Android studio版本最好2.0以上,在1.5上试过各种问题
2、Ndk版本最好是android-ndk-r10d,ndk的路径要在项目根目录下的local.properties下指定,例如ndk.dir=F\:\\android-ndk-r10d
二、加入gradle-experimental插件
1、打开项目根目录下的build.gradle文件,加入
classpath "com.android.tools.build:gradle-experimental:0.7.0"
如下图:
2、打开项目根目录下的gradle->wrapper->gradle-wrapper.propertites,将版本改成2.5,如下图:
经过测试gradle-experimental:0.7.0与gradle-experimental:0.6.0和gradle-2.5-all.zip都能匹配,当然其他版本可以自己测试,这里只是提供一种建议
三、修改Module下的build.gradle
1、打开对应Module下的build.gradle,改之前是下面这样的:
2、默认使用的是com.android.application这个插件,如果要进行jni调试最好换掉这个插件,也就是使用之前加入的gradle-experimental插件,据说不换好像也行,但是没试过。下面贴出具体的配置:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig.with {
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 24
applicationId "com.exampl.myapplication"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.pro'))
}
}
android.ndk {
moduleName = "hello-jni"
ldLibs.addAll(["android", "log"])
stl = "gnustl_shared"
/*
* Other ndk flags configurable here are
* cppFlags.add("-fno-rtti")
* cppFlags.add("-fno-exceptions")
* ldLibs.addAll(["android", "log"])
* stl = "system"
*/
}
android.productFlavors {
create("arm") {
ndk.abiFilters.add("armeabi")
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create("x86") {
ndk.abiFilters.add("x86")
}
create("x86-64") {
ndk.abiFilters.add("x86_64")
}
create("mips") {
ndk.abiFilters.add("mips")
}
create("mips-64") {
ndk.abiFilters.add("mips64")
}
// To include all cpu architectures, leaves abiFilters empty
create("all")
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.android.support:design:24.1.1'
}
注意观察你会发现有很多不一样了,
1. 顶部的插件改成com.android.model.application了,并且整个android配置都要用model包起来
2. defaultConfig变成了defaultConfig.with
3. minSdkVersion变成了minSdkVersion.apiLevel
4. 多了android.ndk这个属性配置,这个就是取代原先的Android.mk文件用的,非常重要,这也是能打断点的原因,如果像之前一样直接加载so,想想都不能打断点
5. 多了android.productFlavors 属性,这个是定义要生成哪些版本的so,不过 调试时是无法看到so的,只有在apk中用winRAR打开才能看到
6. 原先的jni.srcDirs和jniLibs.srcDirs不能用了,目前只知道它默认找的是src/main下的jni目录,至于指定jni路径的方法还没发现
要注意的是一定要按这种格式配置,不然会报各种错误,我刚开始也是没注意到,结果纠结了好久,看来要注意观察啊
四、开始调试jni
1、创建jni目录,上面介绍到默认是到src/main下的jni目录寻找c代码,所以就在这个位置创建jni目录,与以往不同的是这次不需要写Android.mk文件了,只要c代码文件就行了,因为上面介绍过Android.mk的内容实际上写到build.gradle中了,这样也比较方便
2、创建app-native,具体步骤如下:
1)打开Run->Edit Configuration
2) 点击左上角的加号,选择Android Native
3) 选择新建的Android Native,配置General里面的Module为你的目标APP,右边的Debugger选择Hybrid(Hybrid是java和c都能打断点,Native是只能c打断点),配置好后点击OK
4)回到Android Studio主界面,点击Run右边的小三角,会出现一个刚才创建的app-native选项,选中然后Run->Debug就能调试c代码了。仔细观察你会发现原先java里的native函数也能进入了,而且c文件里各个函数都有提示了,而且还能自动生成c文件(对准native函数按Alt+Enter)!这样就达到了我们的目的,像写java代码一样写c代码,不用再担心c代码调试困难的问题了!