前言
之前一直都是使用別人寫(xiě)好的so文件,沒(méi)有親自去寫(xiě)過(guò),于是決定研究一番。先說(shuō)說(shuō)NDK是什么呢?NDK其實(shí)就是一系列工具的集合。NDK有什么用呢?(1) NDK的發(fā)布,使“Java+C”的開(kāi)發(fā)方式終于轉(zhuǎn)正,成為官方支持的開(kāi)發(fā)方式。(2)NDK將是Android平臺(tái)支持C開(kāi)發(fā)的開(kāi)端。
環(huán)境配置
1. 在android studio中的setting-->Android SDK-->SDK Tools選項(xiàng)卡,下載NDK,CMake,LLDB三個(gè)工具

2. 新建一個(gè)項(xiàng)目,并勾選Include C++ support,一路next下去。

3. 配置android studio中ndk路徑。如果ndk路徑?jīng)]有自動(dòng)添加,則點(diǎn)擊select即可。并在local.properties配置文件中檢查是否正確配置路徑。


4. 配置ndk系統(tǒng)環(huán)境變量,并在配置完成后檢查配置是否成功


dos下命令:ndk-build;出現(xiàn)以下信息說(shuō)明配置成功

5. 設(shè)置as。將ndk版本差異檢測(cè)過(guò)濾掉,要不然項(xiàng)目無(wú)法編譯。添加:android.useDeprecatedNdk=true

6. 編寫(xiě)調(diào)用c的java代碼。注意:這里如果方法名報(bào)錯(cuò),不用管他。同時(shí)把MainActivity里的 static {System.loadLibrary("native-lib"); }剪切復(fù)制到新建的MathKit類中
public class MathKit {
public static native int square(int num);
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
}
7. 生成調(diào)用本地方法的.h頭文件。用as自帶的Terminal工具來(lái)生成。
命令:
進(jìn)入你項(xiàng)目的java文件夾下
cd app/src/main/java
com.axaet.ndk是你的完整包名,后面跟具體寫(xiě)有調(diào)用c代碼的java類
javah -jni com.axaet.ndk.MathKit


8. 生成jni文件夾。用于存放.h和.c文件,把步驟7生成的.h頭文件剪切到j(luò)ni文件夾里,并創(chuàng)建對(duì)應(yīng)的.c文件


9. 寫(xiě)c的測(cè)試代碼。include中指向你創(chuàng)建的.h頭文件 Java_com_axaet_ndk_MathKit_square;Java_包名類名方法名(參數(shù))**
#include "com_axaet_ndk_MathKit.h"
//注意方法名要和.h文件里的一樣
JNIEXPORT jint JNICALL Java_com_axaet_ndk_MathKit_square(JNIEnv *env, jclass cls, jint num) {
return num * num;
}
10.在build.gradle中配置生成so文件的信息,主要配置abiFilters
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.axaet.ndk"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "armeabi-v7a", "armeabi", "x86"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
由于android studio 2.2以上使用CMake,所以需要配置CMakeLists.txt文件,修改生成后so文件名稱、添加.c文件的路徑

11. 用Make Project 生成so文件,然后運(yùn)行項(xiàng)目。然后就可以拿到so文件

12. 測(cè)試本地c代碼的調(diào)用。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
//必須先加載so文件,加載so文件在MathKit類中
tv.setText(String.valueOf(MathKit.square(12)).concat(" ").concat(stringFromJNI()));
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
下面是打包jar
13. 刪除一些無(wú)用的資源,如MainActivity,layout等,只留下和JNI有關(guān)的java類

14. 修改module的build.gradle文件
有如下幾個(gè)地方需要修改:
將最前面的apply plugin: 'com.android.application'修改為apply plugin: 'com.android.library'
將defaultConfig修改為:
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
}
SDK的版本可以根據(jù)自己的版本來(lái)改
- 在最后加上
task deleteOldJar(type: Delete) {
delete 'build/outputs/test.jar'
}
task exportJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('build/libs/')
include('classes.jar')
rename ('classes.jar', 'test.jar')
}
exportJar.dependsOn(deleteOldJar, build)
15.導(dǎo)出jar包
首先打開(kāi)Gradle

打開(kāi)app->Tasks->other->exportJar

然后雙擊exportJar就可以了,然后再'build/intermediates/bundles/release/'路徑就可以找到classes.jar
當(dāng)然混淆可以自己視情況添加。
項(xiàng)目源碼
參考文檔[http://www.2cto.com/kf/201610/555224_2.html]
[http://www.open-open.com/lib/view/open1434523603692.html]