02_JNI-Eclipse上的開發(fā)環(huán)境

開發(fā)步驟

  • 確認(rèn)eclipse安裝了CDT , eclipse中查看:Hlep--->Install New Software ---> 點(diǎn)擊右下角already installed --->Plug-ins ---> 查看CDT是否安裝* 新建Android項(xiàng)目* 在MainActivity.java文件中聲明本地方法
public native String  helloFromC();

  • 在項(xiàng)目根目錄下新建jni的Folder
  • 在jni目錄下新建hello.c
  • 在hello.c文件寫與java文件中對應(yīng)的native方法的函數(shù),c中本地函數(shù)命名規(guī)則:Java_包名(.需要換成_)類名本地方法名, 函數(shù)中有兩個(gè)參數(shù):
    1,jobject obj:調(diào)用本地函數(shù)的Java對象,在本例中就是MainActivity實(shí)例
    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到項(xiàng)目目錄下: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的時(shí)候,不能在項(xiàng)目目錄下build,要cd到這個(gè)目錄下,再執(zhí)行ndk-build

  • 再次在命令行中在項(xiàng)目目錄下執(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ā)中常見錯(cuò)誤

方法名

  • native方法名不能包含_,因?yàn)閏語言的函數(shù)命名規(guī)范也是使用的_,會產(chǎn)生沖突,最后會報(bào)Native method not found錯(cuò)誤
  • 如果本地方法一定要有_,那么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到:項(xiàng)目根目錄\bin\classes>
    2,如果是1.7及以上,cd到:項(xiàng)目根目錄\src>
    3,執(zhí)行命令:javah -jni 包名.類名
    在本例中如下:

F:\as\Eclipse\personal\JNI\01-JNIHelloWorld\src>javah -jni com.huachao.jnihelloworld.MainActivity

  • 如果沒有System.loadLibrary("hello");,也會報(bào)Native method not found錯(cuò)誤
  • 注意: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項(xiàng)目
  • 如上所述,在MainActivity中添加native方法
  • 指定項(xiàng)目的NDK目錄:Eclipse視圖中Window --> Preferences -->Android --> NDK --> 選擇NDK目錄(本例中目錄F:\as\plugin\android-ndk-r9d) --> 點(diǎn)擊 apply,然后點(diǎn)擊OK
  • 在Eclipse視圖中,在項(xiàng)目目錄上右鍵點(diǎn)擊-->Android Tools -->Add Native Support --> 輸入自定義名稱(本例中hello) --> 點(diǎn)擊Finish
    注意:
    1,如果Finish點(diǎn)不了,那么可能是上一個(gè)步驟沒做
    2,如果Android Tools中沒有Add Native Support這個(gè)菜單:將資料中的
    com.android.ide.eclipse.ndk_23.0.2.1259578.jar文件拷貝到eclipse的安裝目錄的plugin目錄下,然后重啟Eclipse
  • 將hello.cpp重命名為hello.c,并在Android.mk文件中做相應(yīng)修改
  • 用javah命令生成頭文件
  • 在項(xiàng)目目錄上右鍵點(diǎn)擊 --> Properties -->C/C++ General --> Paths and Symbols --> 選中Includes選項(xiàng)卡 --> Add --> 添加NDK的include目錄(本例F:\as\plugin\android-ndk-r9d\platforms\android-14\arch-arm\usr\include)--> 點(diǎn)擊Apply(會提示是否rebuild,點(diǎn)擊YES) --> 點(diǎn)擊OK
    1, platforms的版本最好選擇Application.mk設(shè)置的最低版本
    2,
    Paste_Image.png
  • 編譯
    1,切換到C/C++視圖
    2,點(diǎn)擊那個(gè)類似錘子的按鈕,進(jìn)行編譯,


    Paste_Image.png
  • 在Java中調(diào)用和上面一樣
  • 提示:運(yùn)行項(xiàng)目最好切換到Java視圖,不然可能會報(bào)錯(cuò)

注意:在eclipse的jni開發(fā)中,包名不能包含下劃線,否則在運(yùn)行時(shí)運(yùn)行不了,但是卻不報(bào)錯(cuò)

在JNI開發(fā)中,指定NDK目錄,是更換workspace的時(shí)候才要做,其他的都是每次新建項(xiàng)目都是要做的

  • 設(shè)置編譯時(shí)不編譯C/C++代碼,也不生成.so庫(當(dāng)so庫已經(jīng)生成完畢時(shí),只是修改了java代碼可以這樣設(shè)置)
    Paste_Image.png

取消上面兩個(gè)紅色箭頭的勾選

繞過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 hellostatic

  • 4.將hellostatic文件傳輸手機(jī)
    adb push hellostatic /data/data/

  • 5.改變文件的授權(quán)
    adb shell chmod 777 /data/data/hellostatic

  • 6.運(yùn)行程序
    adb shell
    cd /data/data
    ./hellostatic

  • 上面的實(shí)質(zhì)就是把.c文件編譯成靜態(tài)庫,然后在命令行執(zhí)行,其實(shí)系統(tǒng)里面已經(jīng)有很多這種可執(zhí)行的文件

    Paste_Image.png

  • 在java中執(zhí)行可執(zhí)行文件
public void binExce(View v) {//點(diǎn)擊事件
     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下測試生效,高版本沒有測試

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容

  • Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實(shí)踐(1)之NDK與JNI...
    AlphaGL閱讀 3,773評論 0 24
  • 一、NDK產(chǎn)生的背景 Android平臺從誕生起,就已經(jīng)支持C、C++開發(fā)。眾所周知,Android的SDK基于J...
    Ten_Minutes閱讀 3,530評論 1 27
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,808評論 25 708
  • 本人非技術(shù)人員,也非專業(yè)測試人員。只是從自己日常使用的角度來對比這幾個(gè)筆記類app。(還有就是,既然這是自己選的題...
    大夢齋閱讀 4,439評論 0 3
  • 我把門打開 門打開了風(fēng) 風(fēng)打開我身體 把污濁灌進(jìn)去 冷酷的風(fēng) 纏繞在我喉結(jié)中 上下翻騰 切割出蒼白肌膚 同歸的人 ...
    以名北墨閱讀 269評論 0 3