Android之NDK開發(fā)初體驗

個人博客地址 http://dandanlove.com/

記得前年開始自己在項目中使用第三方so庫的時候就接觸NDK編程開發(fā)了,只不過哪個時候自己是輸出了"Hello Wrold~!"。如今一年多的時間過去了,回頭拾起之前的代碼再次翻看。

概念

在閱讀文章之前我們首先了解幾個概念

JNI

JNI是Java語言提供的Java和C/C++相互溝通的機制,Java可以通過JNI調(diào)用本地的C/C++代碼,本地的C/C++的代碼也可以調(diào)用java代碼。JNI 是本地編程接口,Java和C/C++互相通過的接口。Java通過C/C++使用本地的代碼的一個關(guān)鍵性原因在于C/C++代碼的高效性。

NDK

NDK是一系列工具的集合。它提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動態(tài)庫,并能自動將so和java應(yīng)用一起打包成apk。這些工具對開發(fā)者的幫助是巨大的。它集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺、ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。它可以自動地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作。

ARM

早起Android只支持ARMv5的CPU架構(gòu),而發(fā)展到現(xiàn)在,支持一下7種架構(gòu):


arm.jpg

世界在進步,cup在arm基礎(chǔ)上不斷升級優(yōu)化。每種架構(gòu)關(guān)聯(lián)著一種ABI(application binary interface應(yīng)用程序二進制接口),所以每一種架構(gòu)都對應(yīng)一個.so文件,但都兼容arm。對于我們Android開發(fā)者來說,我們的app需要能在大多數(shù)手機上運行。所以要么我們所有arm類型都兼容,要么只兼容armeabi。兼容所有CPU架構(gòu)類型是在性能上比較好,但是同時它也造成了apk體積的劇增(PS:我們之前的項目因為接入so庫后導(dǎo)致apk體積劇增,最后只支持armeabi一種類型了)。

搭建環(huán)境

Java環(huán)境配置(略)

AndroidSDK環(huán)境配置(略)

NDK環(huán)境配置

本文主要講述NDK環(huán)境配置:

  • 下載對應(yīng)操作系統(tǒng)的NDK
  • 解壓文件(windows隨意解壓,Ubuntu解壓在bin目錄下)
  • windows環(huán)境下配置


    windows-ndk.jpg
  • Ubuntu環(huán)境下配置
    修改系統(tǒng)環(huán)境變量
    sudo gedit /etc/profile
    在profile文件下面添加,保存并退出
    export ANDROID_NDK= ndk路徑
    export PATH=$ANDROID_NDK:$PATH
    source /etc/profile

查看是否配置成功

im@58user:~/StudioProjects/NDKDemo/app/src/main/java$ ndk-build -v
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
該程序為自由軟件,詳情可參閱版權(quán)條款。在法律允許的范圍內(nèi)
我們不作任何擔保,這包含但不限于任何商業(yè)適售性以及針對特
定目的的適用性的擔保。

 這個程序創(chuàng)建為 x86_64-pc-linux-gnu

Android studio環(huán)境配置

android-ndk-env-config.jpg

以上是下邊使用Android studio 進行NDK開發(fā)的基礎(chǔ),下邊我們進入真正的開發(fā)環(huán)節(jié)。

NDK開發(fā)環(huán)節(jié)

native方法的定義

為了方便,我直接將native方法定義在了Activity當中

public class MainActivity extends AppCompatActivity {
   //加載so庫,libjnilib.so文件
    static {
        System.loadLibrary("jnilib");
    }
    //定義native方法
    private native String getStringForNative();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((TextView) findViewById(R.id.text)).setText(getStringForNative());
    }
}

gradle配置

android {
    /**略**/
    defaultConfig {
        applicationId "ndk.tzx.com.ndkdemo"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk {
            //定義生成的mk文件中的model名稱
            moduleName "jnilib"
        }
    }
    sourceSets {
        main {
            //引入so路徑
            jni.srcDirs = ['src/main/jni']
        }
    }
   /**略**/
}

創(chuàng)建jni目錄

new-jni.jpg

生成C++head文件

make-.c.jpg

執(zhí)行完改命令會在main/jni目錄下生成對應(yīng)的頭文件

ndk-build.cpp.jpg

native方法的實現(xiàn)

然后我們在main/jni目錄下創(chuàng)建cpp文件并進行native方法的實現(xiàn)

  • include頭問件
  • 實現(xiàn)方法
    這一步經(jīng)常有好多人會遇到錯誤,只因方法名寫錯!
edit.cpp.jpg

構(gòu)建并運行出結(jié)果

arm-&-mk.jpg

上圖是項目build后的結(jié)果,在app/build/intermediates/ndk/debug目錄下有l(wèi)ib文件夾,obj文件夾和Android.mk文件。
在Android.mk這個文件當中我們定義生成so的名稱,生成so對應(yīng)cpp文件的路徑和so輸出的路徑。
lib目錄下我們可以看到各種類型的CPU架構(gòu)下的so文件。

如果以上過程都沒有問題的話,那么恭喜你整個項目就可以直接運行了。

踩坑需要一步一步來

build項目的時候遇到下邊問題:

Android.mk生成問題

ndk-intergration.jpg

直接在gradle.properties文件尾部添加android.useDeprecatedNdk=true

so生成問題

Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/bin/android-ndk-r13b/ndk-build.cmd'' finished with non-zero exit value 2

使用Android.md文件生成so的時候可能會遇到這樣的問題:
解決辦法1:

將Android.mk文件copy到j(luò)ni目錄下和.h與.cpp文件放在同一級目錄,然后在該目錄下執(zhí)行ndk-build。

ndk-build.jpg

這種方法也肯能報錯:

Error:(15) *** Android NDK: Aborting.    .  Stop.
Android NDK: /home/im/StudioProjects/NDKDemo/app/src/main/jni/Android.mk: Cannot find module with tag 'core' in import path    
Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined ?    
Android NDK: The following directories were searched:    
Android NDK:         
make: Entering directory `/home/im/StudioProjects/NDKDemo/app/src/main/jni'
make: Leaving directory `/home/im/StudioProjects/NDKDemo/app/src/main/jni'
:app:buildNative FAILED
Error:Execution failed for task ':app:buildNative'.
> Process 'command '/bin/android-ndk-r13b/ndk-build'' finished with non-zero exit value 2

遇到這種情況,偶查了很多資料最后才解決(參見解決方法2)

解決方法2:

安裝最新的ndk(_

運行問題

整個項目可以運行安裝的時候是不是很爽,但是還可能遇到下邊的問題:

$ adb shell am start -n "ndk.tzx.com.ndkdemo/ndk.tzx.com.ndkdemo.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Error while executing: am start -n "ndk.tzx.com.ndkdemo/ndk.tzx.com.ndkdemo.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=ndk.tzx.com.ndkdemo/.MainActivity }
Error type 3
Error: Activity class {ndk.tzx.com.ndkdemo/ndk.tzx.com.ndkdemo.MainActivity} does not exist.

Error while Launching activity

這問題偶也整了好久,網(wǎng)上大多數(shù)解釋為native方法名不匹配,最后重新寫cpp文件也成功解決。

心好累!~!復(fù)習之前的東西還是要當初做好筆記啊。

想閱讀作者的更多文章,可以查看我 個人博客 和公共號:

振興書城

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android游戲開發(fā)實踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實踐(1)之NDK與JNI...
    AlphaGL閱讀 3,910評論 0 24
  • 一、NDK產(chǎn)生的背景 Android平臺從誕生起,就已經(jīng)支持C、C++開發(fā)。眾所周知,Android的SDK基于J...
    Ten_Minutes閱讀 3,726評論 1 27
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,058評論 25 709
  • 神農(nóng)嘗草識黃花,世代栽培品質(zhì)佳。 大嫂采收頭滴汗,幺姑翻曬面飛霞。 觀光賞景游人醉,攝影題詩騷客夸。 補腦養(yǎng)顏純綠...
    艾思閱讀 2,332評論 6 6
  • 所有的故事,都有個結(jié)局。但幸運的是,我們的生活中,每個結(jié)局都會變成一個新的開始。 如果有一天,我變得沒心沒肺,請記...
    5star閱讀 707評論 0 0

友情鏈接更多精彩內(nèi)容