開發(fā)步驟
- 確認(rèn)eclipse安裝了CDT 摘仅, eclipse中查看:Hlep--->Install New Software ---> 點擊右下角already installed --->Plug-ins ---> 查看CDT是否安裝* 新建Android項目* 在MainActivity.java文件中聲明本地方法
public native String helloFromC();
- 在項目根目錄下新建jni的Folder
- 在jni目錄下新建hello.c
- 在hello.c文件寫與java文件中對應(yīng)的native方法的函數(shù),c中本地函數(shù)命名規(guī)則:Java_包名(
.
需要換成_
)類名本地方法名形耗,函數(shù)中有兩個參數(shù):
1笤休,jobject obj:調(diào)用本地函數(shù)的Java對象,在本例中就是MainActivity實例
2倒庵,JNIEnv* env:是結(jié)構(gòu)體JNINativeInterface 的二級指針,JNIEnv是結(jié)構(gòu)體 JNINativeInterface 的一級指針,JNINativeInterface結(jié)構(gòu)體中定義了大量的函數(shù)指針,這些函數(shù)指針在JNI開發(fā)中會經(jīng)常使用
3亡嫌,(*env)->:調(diào)用結(jié)構(gòu)體中的函數(shù)指針
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
jstring Java_com_huachao_jnihelloworld_MainActivity_helloFromC(JNIEnv* env , jobject thiz){
char* cstr = "hello from c";
return (*env)->NewStringUTF(env,cstr);
}
- 配置ndk環(huán)境變量(path中添加ndk路徑)
- 在命令行cd到項目目錄下:F:\as\Eclipse\personal\JNI\01-JNIHelloWorld>
- 執(zhí)行ndk-build命令,提示
Android NDK: WARNING: APP_PLATFORM android-21 is larger than android:minSdkVers
on 8 in ./AndroidManifest.xml
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk
- 在jni目錄下掘而,新建Android.mk文件
LOCAL_PATH := $(call my-dir)//設(shè)置為當(dāng)前目錄
include $(CLEAR_VARS) //清空變量
LOCAL_MODULE := hello//編譯生成的文件名稱
LOCAL_SRC_FILES := hello.c//.c源文件名稱
include $(BUILD_SHARED_LIBRARY)
注意:
1挟冠,LOCAL_MODULE := hello,編譯后镣屹,編譯器會給文件添加lib
前綴和.so
后綴圃郊,例如本例生成libhello.so
2价涝,若新建的文件夾名不是jni,或者修改了jni的文件夾名稱女蜈,則在ndk-build的時候,不能在項目目錄下build,要cd到這個目錄下伪窖,再執(zhí)行ndk-build
- 再次在命令行中在項目目錄下執(zhí)行ndk-build命令逸寓,提示Install,生成.so文件,表示成功
- 在MainActivity.java中調(diào)用
public class MainActivity extends Activity {
static{
System.loadLibrary("hello");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public native String helloFromC();
public void onClick(View v) {
String c = helloFromC();
Toast.makeText(this, c, Toast.LENGTH_LONG).show();
}
}
開發(fā)中常見錯誤
方法名
- native方法名不能包含
_
覆山,因為c語言的函數(shù)命名規(guī)范也是使用的_
竹伸,會產(chǎn)生沖突,最后會報Native method not found
錯誤 - 如果本地方法一定要有
_
,那么c函數(shù)_
后加1區(qū)分簇宽,例如:
public native String hello_FromC();
jstring Java_com_huachao_jnihelloworld_MainActivity_hello_1FromC(JNIEnv* env , jobject thiz){
}
- 如果native名字太復(fù)雜勋篓,下劃線太多,可以使用javah命令自動生成c的函數(shù)名
1魏割,如果是jdk1.6譬嚣,cd到:項目根目錄\bin\classes>
2,如果是1.7及以上钞它,cd到:項目根目錄\src>
3拜银,執(zhí)行命令:javah -jni 包名.類名
在本例中如下:
F:\as\Eclipse\personal\JNI\01-JNIHelloWorld\src>javah -jni com.huachao.jnihelloworld.MainActivity
- 如果沒有
System.loadLibrary("hello");
,也會報Native method not found
錯誤 - 注意:System.loadLibrary("hello");加載的庫名稱是
Android.mk
中LOCAL_MODULE := hello的名稱,而不是生成的.so
文件的名稱
Application.mk配置
多平臺
- 如果Application.mk沒有文件遭垛,或者在Application.mk文件中不指定APP_ABI,在NDK默認(rèn)只編譯
armeabi
的平臺的庫 - 在jni目錄下新建Application.mk文件
1, APP_ABI := all //所有平臺
2, APP_ABI := armeabi-v7a
3, APP_ABI := x86
4, APP_ABI := mips
5, APP_ABI := armeabi armeabi-v7a x86 mips //也是所有平臺
SDK版本配置
- 在Application.mk添加
APP_PLATFORM := android-11
- 版本對應(yīng)
android-3 -> Official Android 1.5 system imagesandroid-4 -> Official Android 1.6 system imagesandroid-5 -> Official Android 2.0 system imagesandroid-6 -> Official Android 2.0.1 system imagesandroid-7 -> Official Android 2.1 system imagesandroid-8 -> Official Android 2.2 system imagesandroid-9 -> Official Android 2.3 system imagesandroid-14 -> Official Android 4.0 system imagesandroid-18 -> Official Android 4.3 system images
簡單開發(fā)流程
- 新建Android項目
- 如上所述尼桶,在MainActivity中添加native方法
- 指定項目的NDK目錄:Eclipse視圖中Window --> Preferences -->Android --> NDK --> 選擇NDK目錄(本例中目錄
F:\as\plugin\android-ndk-r9d
) --> 點擊 apply,然后點擊OK - 在Eclipse視圖中,在項目目錄上右鍵點擊-->Android Tools -->Add Native Support --> 輸入自定義名稱(本例中
hello
) --> 點擊Finish
注意:
1锯仪,如果Finish點不了泵督,那么可能是上一個步驟沒做
2,如果Android Tools中沒有Add Native Support這個菜單:將資料中的
com.android.ide.eclipse.ndk_23.0.2.1259578.jar
文件拷貝到eclipse的安裝目錄的plugin目錄下庶喜,然后重啟Eclipse - 將hello.cpp重命名為hello.c幌蚊,并在
Android.mk
文件中做相應(yīng)修改 - 用javah命令生成頭文件
- 在項目目錄上右鍵點擊 --> Properties -->C/C++ General --> Paths and Symbols --> 選中Includes選項卡 --> Add --> 添加NDK的include目錄(本例
F:\as\plugin\android-ndk-r9d\platforms\android-14\arch-arm\usr\include
)--> 點擊Apply(會提示是否rebuild,點擊YES) --> 點擊OK
1, platforms的版本最好選擇Application.mk設(shè)置的最低版本
2,
Paste_Image.png
-
編譯
1,切換到C/C++視圖
2溃卡,點擊那個類似錘子的按鈕溢豆,進(jìn)行編譯,
Paste_Image.png
- 在Java中調(diào)用和上面一樣
- 提示:運行項目最好切換到Java視圖瘸羡,不然可能會報錯
注意:在eclipse的jni開發(fā)中漩仙,包名不能包含下劃線,否則在運行時運行不了犹赖,但是卻不報錯
在JNI開發(fā)中队他,指定NDK目錄,是更換workspace的時候才要做峻村,其他的都是每次新建項目都是要做的
- 設(shè)置編譯時不編譯C/C++代碼麸折,也不生成
.so
庫(當(dāng)so庫已經(jīng)生成完畢時,只是修改了java代碼可以這樣設(shè)置)
Paste_Image.png
取消上面兩個紅色箭頭的勾選
繞過JNI調(diào)用C代碼
廣泛使用的地方:
1粘昨,自定制平板垢啼,機(jī)頂盒
2窜锯,Android手機(jī)病毒
3,黑客操作純c語言開發(fā)程序 芭析,步驟如下:
1.下載編譯器和鏈接器軟件.Sourcery G++ Lite Edition for ARM.
arm-none-linux-gnueabi-gcc.exe是編譯命令
bin/arm-none-linux-gnueabi-ld.exe是鏈接命令
- 2.編寫c源文件
#include <stdio.h>
int main()
{
printf("Hello, Android!\n");
return 0;
}
3.編譯hello.c源文件
進(jìn)入cmd
執(zhí)行 arm-none-linux-gnueabi-gcc HelloWorld.c -static -o hellostatic4.將hellostatic文件傳輸手機(jī)
adb push hellostatic /data/data/5.改變文件的授權(quán)
adb shell chmod 777 /data/data/hellostatic6.運行程序
adb shell
cd /data/data
./hellostatic-
上面的實質(zhì)就是把
.c
文件編譯成靜態(tài)庫锚扎,然后在命令行執(zhí)行,其實系統(tǒng)里面已經(jīng)有很多這種可執(zhí)行的文件
Paste_Image.png
- 在java中執(zhí)行可執(zhí)行文件
public void binExce(View v) {//點擊事件
try {
// Process process = Runtime.getRuntime().exec("/data/data/hello");//hello是我們自己編譯并且放入的庫文件
Process process = Runtime.getRuntime().exec("ps");
InputStream is = process.getInputStream();
DataInputStream dis = new DataInputStream(is);
String res ;
StringBuilder sb = new StringBuilder();
while ((res = dis.readLine()) !=null) {
sb.append(res);
sb.append("\n");
}
System.out.println("--->"+sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
注意:上述步驟只在Android 4.x下測試生效馁启,高版本沒有測試