温馨提示:如果你的 Android Studio 版本在 2.2 以上 , 建议你用 cMake 的新姿势进行 NDK 开发 : http://www.jianshu.com/p/e03028f826d7
我相信你会爱上 cMake 的;
1. 环境搭建
俗话说 “工欲善其事,必先利其器” ;所以咱还是得先下载 ndk;
下载地址 :https://developer.android.com/ndk/downloads/index.html(需要翻墙,你懂得)
或者可以直接在 Android Studio 里面下载,这就可以免去翻墙,
File-->Project Structure
![](https://img.haomeiwen.com/i3878387/b385baab12b75c73.png)
如果你已经下载,直接选择你 ndk 的位置;
如果没有下载,在红色框这个位置会有位置提示你下载,点击下载就行;
添加 ndk 后你会在 local.properties 这个文件看到(路径取决于你 ndk 的位置):
![](https://img.haomeiwen.com/i3878387/675897aafae1c61a.png)
莫慌,还差最后一步:
![](https://img.haomeiwen.com/i3878387/44c83fbc26313850.png)
在此处加上这句代码:android.useDeprecatedNdk=true
好了,ndk 环境搭建完毕!
2. java 代码与 c 代码编写
首先新建个 java 类
public class JniTest{
static {
System.loadLibrary("jary");
}
public native String getString();
}
然后重新编译下你的 Project: Build-->Make Project(Ctrl+F9)
重新编译之后就可以在对应的文件夹看到编译后的 JniTest.class
C:\ASworkspace\MyJniTest\app\build\intermediates\classes\debug\jary\com\myjnitest
![](https://img.haomeiwen.com/i3878387/574a01073cd00517.png)
下一步来看怎么生成 .h 的文件
在 studio 打开 Terminal 命令行工具,打开步骤是 View-->Tool Windows-->Terminal (Alt+F12)
在命令行中先进入到工程的 main 目录下
输入命令:javah -d jni -classpath 自己编译后的 class 文件的绝对路径
例如:javah -d jni -classpath
C:\ASworkspace\MyJniTest\app\build\intermediates\classes\debug jary.com.myjnitest.JniTest
注意 debug 后面是有个空格的,如图:
![](https://img.haomeiwen.com/i3878387/5e54783e476efd12.png)
命令执行后会在 main 目录下(在哪个目录下执行就会在哪个目录下生成 .h 文件)自动生成 “jni” 文件夹,同时生成一个 .h 的文件
![](https://img.haomeiwen.com/i3878387/a5f6f39727c4db46.png)
这个 .h 文件可不做修改 ;默认就行
现在我们来写一个测试的 C 文件 jary.c 同 .h 文件一样放到 jni 文件夹下,代码如下:
![](https://img.haomeiwen.com/i3878387/d8b34969fb7d91b9.png)
依赖刚才生成的 .h 头文件 ; 方法名与 .h 里面方法名保持一致 ;
最后在 build.gradle defaultConfig 中添加如下代码
ndk {
moduleName "jary" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
stl "stlport_static" //打开.c 的 debug , 下面第 4 点会讲到
}
到这里,jni 调 C 就完成了,现在我们来测试一下,写个 TextView 显示一下调用的 C:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvJni = (TextView) findViewById(R.id.tvJni);
tvJni.setText(new JniTest().getString());
}
}
效果如下图 :
![](https://img.haomeiwen.com/i3878387/8984ce7b799defa1.png)
3. 生成 .so 以及调用
编译后的 .so 文件如下图路径:
![](https://img.haomeiwen.com/i3878387/f227e3f7abde6515.png)
根据这个路径就可以找到指定输出的三种体系结构下的 .so 文件,然后把 .so 文件复制出来,如下图所示的放到 jniLibs 文件夹下面,如下图:
![](https://img.haomeiwen.com/i3878387/735806320bd45c8d.png)
注意: 放到 jniLibs 文件夹下面,build.gradle 里面什么都可以不用配置
还有一种方式是将 .so 文件 放在 libs 文件夹下面,注意在 build.gradle 添加如下配置:
![](https://img.haomeiwen.com/i3878387/9852dc6269f66dd4.png)
4. 关于ndk开发在 .c 文件里面的 debug
首先在 build.gradle 中添加如下代码 :
android {
... ...
defaultConfig {
... ...
ndk {
moduleName "jary" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
stl "stlport_static" //打开.c 的 debug (此句是打开的debug的关键)
}
}
buildTypes {
debug {
jniDebuggable true //此句不加在真机上 debug 不受影响,但是在虚拟机上不能 debug
}
}
配置后如下图 ,会出现一个 app-native,选择此项你就可以尽情的 debug 了:
![](https://img.haomeiwen.com/i3878387/0c1d36a3a9f2d5df.png)
debug 如下图:
![](https://img.haomeiwen.com/i3878387/5acb22ff62d4befe.png)
网友评论
还不行可以网上找下 AS 用命令生成 .so 文件
Process: com.my_project, PID: 4880
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.my_project.test_jni.interfaces.SimpleJNIinterface.sayName() (tried Java_com_my_1project_test_1jni_interfaces_SimpleJNIinterface_sayName and Java_com_my_1project_test_1jni_interfaces_SimpleJNIinterface_sayName__)
at com.my_project.test_jni.interfaces.SimpleJNIinterface.sayName(Native Method)
at com.my_project.test_jni.activity.MakeJNIActivity.initView(MakeJNIActivity.java:31)
at com.my_project.test_jni.activity.MakeJNIActivity.onCreate(MakeJNIActivity.java:27)
为什么我有这个错误
static {
System.loadLibrary("jary");
}
public native String add(int num1, int num2);
public native String getString();
}
我里面写2个方法,但是生成的.只有一个方法 这是为什么呀?
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_z_ndkxx_JniTest */
#ifndef _Included_com_z_ndkxx_JniTest
#define _Included_com_z_ndkxx_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_z_ndkxx_JniTest
* Method: getString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_z_ndkxx_JniTest_getString
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.congwiny.jnitestdemo2"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
moduleName "congwiny" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
stl "stlport_static" //打开.c 的 debug , 下面第 4 点会讲到
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
jniDebuggable true //此句不加在真机上 debug 不受影响,但是在虚拟机上不能 debug
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
> com.android.ide.common.process.ProcessException: Error while executing process /Users/congwiny/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/Android.mk APP_PLATFORM=android-25 NDK_OUT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/congwiny/Develop/Android/mydemo/JNITestDemo2/app/build/intermediates/ndk/debug/lib NDK_DEBUG=1 APP_STL=stlport_static APP_ABI=armeabi-v7a,armeabi,x86}
到最后把compileSdkVersion和targetSdkVersion都改成24才行!!大家注意啊
你可以先 clean 一下试试。
我用这一串是成功的,你看你环境ok不。。。