前言
本文只涉及在Android Studio(以下簡稱as)中ndk的使用,基本不涉及原理性講解。
ndk&cmake
在最新的as中 使用ndk,都是通過配置cmake腳本實現的。
CMake是個開源的跨平臺自動化建構系統,它用配置文件控制建構過程(build process)的方式和Unix的Make相似,只是CMake的配置文件取名爲CmakeLists.txt——[bing網典]
cmake最大的特點就是跨平臺,可以根據不同平臺生成相應的腳本,在linux下生成 .sh文件,windows下就就可以生成.bat文件,當然 我們編譯so庫也可以生成makefile文件,但是cmake直接使用的腳本文件是需要自己編寫的。就生成as中生成so來說,大致流程就是cmake通過cmakelist腳本生成makefile腳本,ndk使用make工具執行.mk腳本,即使用相應的編譯或其他工具執行真正的操作。
對於較小型 且無跨平臺需求的項目 ,直接通過.mk文件編譯就可以了。
準備
- 在使用ndk開發前,需要做些前期準備
- ndk配置
- 在project structure中
若尚未下載,點擊Download下載即可. - javah命令配置
- javah就是將使用native方法的類生成c或c++的頭文件,
當然,如果對jni的語法已經非常熟悉可以忽略此操作.
在as的setting中 進入External Tools:
可以直接複製JDKPath /bin/javah
-classpath . -jni -oModuleFileDir \src\main\jni$PromptFileClass ModuleFileDir$\src\main\java
配置完以後 就可以看到
創建工程
正常方式創建一個android 工程。創建完成後在在main下新建一個jni文件夾。
創建我們的加載動態庫的類,並添加調用本地方法的api。
public class NativeTest {
public native String getNativeText(String name);
public native int getNativeNum(int num1,int num2);
static {
System.loadLibrary("ndk_test");
}
}
通過javah動態生成.h文件,執行javah命令後,會在在jni文件夾裏創建一個.h文件,文件名 可以自定義.
編寫.c或 .cpp文件,導入.h文件,並實現頭文件中聲明的方法.
編寫makefile文件
下面就是配置gradle文件了,直接貼gradle文件
//
// Created by gqs on 2016/10/26.
//
#include <jni.h>
#include <string.h>
#include "jni_test.h"
/**
* 工具方法
* 作用: 把java中的string 轉化成一個c語言中的char數組
* 接受的參數 envjni環境的指針
* jstr 代表的是要被轉化的java的string 字符串
* 返回值 : 一個c語言中的char數組的首地址 (char 字符串)
*/
char* jstring2CStr(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env,"java/lang/String");
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
jmethodID mid =
(*env)->GetMethodID(env,clsstring,"getBytes","(Ljava/lang/String;)[B");
// String.getByte("GB2312");
jbyteArray barr=
(jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);
jsize alen = (*env)->GetArrayLength(env,barr);
jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
if(alen > 0)
{
rtn = (char*)malloc(alen+1); //"\0"
memcpy(rtn,ba,alen);
rtn[alen]=0;
}
(*env)->ReleaseByteArrayElements(env,barr,ba,0); //
return rtn;
}
JNIEXPORT jstring JNICALL Java_com_gqs_ndkdemo_NativeTest_getNativeText
(JNIEnv *env, jobject obj, jstring name)
{
char str[50];
char *hello = "Hello ";
strcpy (str,hello);
char* cstr = jstring2CStr(env,name);
strcat(str,cstr);//拼接兩個字符串
return (*env)->NewStringUTF(env,str);
}
/*
* Class: com_gqs_ndkdemo_NativeTest
* Method: getNativeNum
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_gqs_ndkdemo_NativeTest_getNativeNum
(JNIEnv *env, jobject obj, jint num1, jint num2)
{
return num1+ num2;
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.gqs.ndkdemo"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
//生成so庫的名稱 要和Android.mk文件指定的一直
moduleName "jni_test"
//生成支持不同cpu類型的動態庫
abiFilters "armeabi","armeabi-v7a","x86"
}
}
externalNativeBuild {
ndkBuild {
//配置makefile文件路徑
path 'src/main/jni/Android.mk'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
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'
})
testCompile 'junit:junit:4.12'
}
OK ,下面就可以直接運行了,good luck!
代碼下載:http://download.csdn.net/detail/gqs519/9672544