0%

使用Android Studio进行NDK开发

记录一下使用Android Studio进行NDK开发的过程。

快速入门

新建一个工程AndroidNdkFirst,Minimum SDK根据自己需要选择,我用的是API 16(即Android 4.1),Activity选择Empty Activity。

配置NDK

File >> Project Structure >> Download Android NDK
之后就开始下载android-ndk-r12-beta1-windows-x86_64.zip。

下载NDK

下载完了之后自动解压安装到android-sdk根目录下的ndk-bundle目录。安装完成后自动填入了ndk路径,如下图,我这里是D:\Programs\android-sdk\ndk-bundle

设置NDK路径

配置Gradle

  • 在grandle.properties文件末尾增加代码:
1
android.useDeprecatedNdk=true
  • 修改app/build.gradle文件,在android{defaultConfig{…}}内部增加代码:
1
2
3
4
5
ndk {
moduleName "ndkfirst"
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}

具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion '23.0.3'
defaultConfig {
applicationId "com.leon.androidndkfirst"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"

ndk {
moduleName "ndkfirst" // 生成的so库
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}

}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
}

编写NDK代码

以上配置完了就可以开发NDK了。
先新建ndk测试类NdkTest.java,package为com.leon.androidndkfirst,内容如下:

1
2
3
4
5
6
7
8
9
10
package com.leon.androidndkfirst;

public class NdkTest {
static {
//so库名称,对应libndkfirst.so
System.loadLibrary("ndkfirst");
}
public static native String getStringFromNative();
}

注意System.loadLibrary(“ndkfirst”)导入的so库要与Gradle中ndk配置一致。
接着Build >> Make Project,生成对应的NdkTest.class文件,文件所在位置app/build/intermediates/classes/debug/com/leon/androidndkfirst/NdkTest.class。如下图所示:

类文件位置

然后使用命令行生成c头文件,
打开Terminal终端,先进到项目的app/src/main目录,cd app/src/main
用 javah 命令生成头文件,
javah -d jni -classpath ../../build/intermediates/classes/debug com.leon.androidndkfirst.NdkTest

javah 命令

执行完了之后在main目录下生成jni文件夹并在其中生成头文件com_leon_androidndkfirst_NdkTest.h文件,结果如下:

javah 命令

根据生成的.h头文件,在jni目录下新建c源文件ndk.c如下:

1
2
3
4
5
6
#include "com_leon_androidndkfirst_NdkTest.h"
JNIEXPORT jstring JNICALL Java_com_leon_androidndkfirst_NdkTest_getStringFromNative
(JNIEnv *env, jclass clazz) {
// 返回一条字符串
return (*env)->NewStringUTF(env,"这是来自native的string");
}

调用Native方法

在Activity文件中调用getStringFromNative()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.leon.androidndkfirst;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
private TextView tvNative;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvNative = (TextView) findViewById(R.id.tvNative);
tvNative.setText(NdkTest.getStringFromNative());
}
}

运行结果

运行到模拟器的结果如下:

运行结果

并且,在app/build/intermediates/ndk/debug/lib目录下生成了so库文件:

so库文件位置

小结

根据上面的过程,在android studio上进行ndk开发可以总结如下几步:

Gradle配置

一是在grandle.properties文件中添加android.useDeprecatedNdk=true;
二是在app/build.gradle文件中的android{defaultConfig{…}}内部添加NDK配置:

1
2
3
4
ndk {
moduleName "动态库名"
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}

Native

加载动态库

1
2
3
static {
System.loadLibrary("ndkfirst"); //动态库库名称,对应libndkfirst.so
}

定义Native方法

在新建的类中定义Native方法:

1
public static native getStringFromNative ();

生成头文件

进入app/src/main目录,用javah命令生成头文件:

1
javah -d jni -classpath ../../build/intermediates/classes/debug com.leon.androidndkfirst.NdkTest

编写JNI方法

在app/src/main/jni目录下即可新建源文件后进行编写。

Java调用

在Activity中可以直接调用NdkTest.getStringFromNative()方法。