| 目錄(?)[+] |
較新的 NDK 版本是 r10b,Android Studio 對(duì) NDK 開(kāi)發(fā)的支持還處于構(gòu)思階段,所以很多工作比如用 Javah 生成頭文件等工作還要自己做。今天用一個(gè)例子來(lái)演示 AS 中的 NDK 開(kāi)發(fā)。
在此項(xiàng)目中新建一個(gè) Module 叫 ndklibrary,作為 so 庫(kù)單獨(dú)劃出來(lái)。在 library 中新建一個(gè) Java 類(lèi) SecondLib,內(nèi)容如下:
package com.linc.ndklibrary;
/**
* Created by linc on 15-3-29.
*/
public class SecondLib {
// Native implementation
static {
System.loadLibrary("SecondLib");
}
//int array
public static native int[] intMethod();
//string array
public static native String[] stringMethod();
}
Build—>Make Module’ndklibrary’,這樣 SecondLib 就編譯完成了,通過(guò) SecondLib.class,用 Javah 生成 C 的頭文件,如下:
AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ javah -d jni -classpath ../../build/intermediates/classes/debug com.linc.ndklibrary.SecondLib
AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ ls
AndroidManifest.xml java jni res
AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ ls jni/
com_linc_ndklibrary_SecondLib.h
頭文件內(nèi)容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_linc_ndklibrary_SecondLib */
#ifndef _Included_com_linc_ndklibrary_SecondLib
#define _Included_com_linc_ndklibrary_SecondLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_linc_ndklibrary_SecondLib
* Method:intMethod
* Signature: ()[I
*/
JNIEXPORT jintArray JNICALL Java_com_linc_ndklibrary_SecondLib_intMethod
(JNIEnv *, jclass);
/*
* Class: com_linc_ndklibrary_SecondLib
* Method:stringMethod
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_com_linc_ndklibrary_SecondLib_stringMethod
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
在 jni 目錄中新建 c 文件 SecondLib.c 與頭文件對(duì)應(yīng),分別實(shí)現(xiàn)上述兩個(gè)方法,內(nèi)容如下:
#include "com_linc_ndklibrary_SecondLib.h"
const static int length=10;
//int array
JNIEXPORT jintArray JNICALL Java_com_linc_ndklibrary_SecondLib_intMethod
(JNIEnv *env, jclass obj)
{
jintArray array;
array=(*env)->NewIntArray(env,10);
int i=1;
for(;i<=10;++i)
{
(*env)->SetIntArrayRegion(env,array,i-1,1,&i);
}
//get array length
int len=(*env)->GetArrayLength(env,array);
//array content
jint* elems=(*env)->GetIntArrayElements(env,array,0);
return array;
}
//string array
JNIEXPORT jobjectArray JNICALL Java_com_linc_ndklibrary_SecondLib_stringMethod
(JNIEnv *env, jclass obj)
{
jclass class=(*env)->FindClass(env,"java/lang/String");
jobjectArray string=(*env)->NewObjectArray(env,(jsize) length,
class,0);
jstring jstr;
char* _char[]={"my ","name ","is ",
"linc!!","正在","學(xué)習(xí)",
"JNI","和","NDK","技術(shù)!"
};
int i=0;
for(;i<length;++i)
{
jstr=(*env)->NewStringUTF(env,_char[i]);
(*env)->SetObjectArrayElement(env,string,i,jstr);
}
return string;
}
在 local.properties 中加入 ndk路徑:
ndk.dir=/opt/ndk/android-ndk-r10b
然后在 ndklibrary 的 build.gradle 中 defaultConfig 中加入 ndk 定義,如下:
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk{
moduleName "SecondLib"
}
}
這樣就可以直接編譯了,不用自己編寫(xiě) make 文件了。
Build—>Make Module’ndklibrary’,生成的 so 如下:
AndroidStudioProjects/SecondNdkTest$ find -name *.so
./ndklibrary/build/intermediates/ndk/debug/lib/armeabi/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/armeabi-v7a/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/mips/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/x86/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/armeabi/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/armeabi-v7a/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/mips/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/x86/libSecondLib.so
注:
至于直接在 Activity 中用 native 的方法請(qǐng)參考下面的前兩個(gè)鏈接。我遇到了問(wèn)題沒(méi)有得到解決:
$ javah -d jni -classpath /opt/sdk/platforms/android-5.1/android.jar;../../build/intermediates/classes/debug com.linc.secondndktest.MainActivity
Error: no classes specified
bash: ../../build/intermediates/classes/debug/: Is a directory