JNI開發(fā)(基于AS高低版本說明)

更新了Android Studio版本之后挂捻,在按照之前的方式搭建JNI的開發(fā)環(huán)境吃挑,發(fā)現(xiàn)不斷的報錯,通過查看日志發(fā)現(xiàn)羊初,android.useDeprecatedNdk不再支持了讓滨溉,使用CMake or ndk-build。本文介紹了在低版本和高版本上分別怎么實現(xiàn)长赞,以及總結(jié)在搭建過程中遇到的錯誤和解決辦法晦攒。

Android Studio 2.2版本以下

1.首先通過SDKManager-SDK Tools下載NDK插件

2.在local.properties文件里面配置NDK路徑:

一種方式是在該文件中直接填寫NDK的路徑

另一種方式是在SDK Location里面配置:在項目上右鍵->選擇open Moulde Settings

3.在在gradle.properties文件中追加下面代碼:

android.useDeprecatedNdk=true

4.使用native關(guān)鍵字編寫JNI接口

public class JNIUtils {
    public static native String getStringFromC();
}

編寫之后,make project得哆,在工程目build\intermediates\classes\debug\自己的包名下就可以看到編譯后的class文件JNIUtils.class如下圖所示:


5.使用javah命令生成.h頭文件

5.1 打開Terminal脯颜,然后在命令行中先進入到工程的build\intermediates\classes\debug目錄下(cd 直接拖拽debug目錄即可)
5.2 輸入命令:javah 包名.類名

javah com.bysj.myapplication.JNIUtils

在debug目錄下就會生成對應(yīng)的頭文件(.h文件)


6. 實現(xiàn)上述頭文件里面的方法

6.1 在main目錄下新建jni文件夾



6.2 將上述的頭文件復(fù)制進來,文件名可以隨意該贩据,但是內(nèi)容不能改栋操。
6.3 新建一個c或者c++源文件實現(xiàn)頭文件中的方法,并在源文件中引入頭文件(此處我自己建立的是C++的文件)

#include "com_bysj_jniapplication_JNIUtils.h" //頭文件的名字要對應(yīng)

JNIEXPORT jstring JNICALL Java_com_bysj_jniapplication_JNIUtils_getStringFromC
        (JNIEnv *env, jclass) {
    return env -> NewStringUTF("Hello from C++");
    }

7. 添加NDK配置

7.1 開發(fā)app內(nèi)build.gradle乐设,在android/defaultConfig下面添加ndk配置

android {
       讼庇。。近尚。蠕啄。。戈锻。
 defaultConfig {
      歼跟。。格遭。哈街。。拒迅。
        ndk {
            moduleName "JNISample" //生成so庫的名字
        }
    }
    buildTypes {
    骚秦。她倘。。作箍。硬梁。。
    }
}

7.2 加載so庫胞得,在JNIUtils類中添加以下的代碼:

public class JNIUtils {
    static {
        System.loadLibrary("JNISample");//名字要與build.gradle中配置的一致
    }
    public native static String getStringFromC();
}

最后編譯運行荧止,可以看到結(jié)果:


以上是在AS2.2版本以下這樣做會成功,但是在2.2以后在編譯的時候會報以下的錯誤:

我們仔細看下Log阶剑,大概意思就是說:

  1. android.useDeprecatedNdk不再支持了
  2. 讓使用CMake or ndk-build
  3. 然后還有鏈接
    考慮使用CMake或ndk構(gòu)建集成跃巡。要了解更多信息,請訪問:
    https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile
    首先牧愁,您可以使用Android的ndk構(gòu)建腳本示例插件為您生成:
    /Users/apple/Desktop/AndroidJNITest/app/build/intermediates/ndk/debug/Android.mk
    或者素邪,你可以使用實驗插件:
    https://developer.android.com/r/tools/experimental-plugin.html
    繼續(xù)使用已棄用的NDK編譯60天,設(shè)置在gradle.properties
    android.deprecatedNdkCompileLease = 1523416167903(這個測試不起作用)
    經(jīng)過各種查資料递宅,發(fā)現(xiàn)原來在gradle3.0以上以前這種方法不再支持

所以在AS2.2版本以后進行NDK開發(fā)要使用CMake娘香,下面演示以下具體的實現(xiàn)方法(你會發(fā)現(xiàn)很簡單,省去類很多的事)

Android Studio 2.2版本以上

1. 先通過SDKManager下載:CMake和LLDB

2.在新建項目的時候勾選 Include C++ Support

接下來的步驟跟創(chuàng)建普通項目一樣办龄。

2.1 配置C++支持功能(Customize C++ Support)在Customize C++ Support界面默認即可烘绽。


  • C++ Standard

指定編譯庫的環(huán)境,其中Toolchain Default使用的是默認的CMake環(huán)境俐填;C++ 11也就是C++環(huán)境安接。兩種環(huán)境都可以編庫,至于區(qū)別英融,后續(xù)會跟進盏檐,當前博文使用的是CMake環(huán)境。

  • Exceptions Support

如果選中復(fù)選框驶悟,則表示當前項目支持C++異常處理胡野,如果支持,在項目Module級別的build.gradle文件中會增加一個標識 -fexceptions到cppFlags屬性中痕鳍,并且在so庫構(gòu)建時硫豆,gradle會把該屬性值傳遞給CMake進行構(gòu)建。

  • Runtime Type Information Support

同理笼呆,選中復(fù)選框熊响,項目支持RTTI,屬性cppFlags增加標識-frtti

點擊完成诗赌,Android Studio會自動把JIN開發(fā)的環(huán)境搭建好汗茄,可以直接運行,比起低版本的是不是省很多事懊簟洪碳!

勾選了 Include C++ Support以后递览,會自動在build.gradle中添加以下配置

android {
    compileSdkVersion 27
    defaultConfig {
        。偶宫。非迹。环鲤。纯趋。。冷离。吵冒。
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt" //該文件用于配置JNI項目屬性
        }
    }
}

3.CMakeLists.txt文件說明

CMakeLists.txt文件用于配置JNI項目屬性,主要用于聲明CMake使用版本西剥、so庫名稱痹栖、C/CPP文件路徑等信息,下面是該文件內(nèi)容:

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
            # 設(shè)置so文件名稱
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # 設(shè)置這個so文件為共享.
             # file are automatically included.
             src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
  • cmake_minimum_required(VERSION 3.4.1)
    CMake最小版本使用的是3.4.1瞭空。

    • add_library()
      配置so庫信息(為當前當前腳本文件添加庫)

    • native-lib
      這個是聲明引用so庫的名稱揪阿,在項目中,如果需要使用這個so文件咆畏,引用的名稱就是這個南捂。值得注意的是,實際上生成的so文件名稱是libnative-lib旧找。當Run項目或者build項目是溺健,在Module級別的build文件下的intermediates\transforms\mergeJniLibs\debug\folders\2000\1f\main下會生成相應(yīng)的so庫文件。* SHARED
      這個參數(shù)表示共享so庫文件钮蛛,也就是在Run項目或者build項目時會在目錄intermediates\transforms\mergeJniLibs\debug\folders\2000\1f\main下生成so庫文鞭缭。此外,so庫文件都會在打包到.apk里面魏颓,可以通過選擇菜單欄的Build->Analyze Apk...*查看apk中是否存在so庫文件岭辣,一般它會存放在lib目錄下。

    • src/main/cpp/native-lib.cpp
      構(gòu)建so庫的源文件甸饱。

STATIC:靜態(tài)庫沦童,是目標文件的歸檔文件,在鏈接其它目標的時候使用柜候。
SHARED:動態(tài)庫搞动,會被動態(tài)鏈接,在運行時被加載渣刷。
MODULE:模塊庫鹦肿,是不會被鏈接到其它目標中的插件,但是可能會在運行時使用dlopen-系列的函數(shù)動態(tài)鏈接辅柴。
更詳細的解釋請參考這篇文章:C++靜態(tài)庫與動態(tài)庫

下面的配置實際上與自定義的JNI項目(自定義的so庫)沒有太大關(guān)系瞭吃。

  • find_library()
    這個方法與我們要創(chuàng)建的so庫無關(guān)而是使用NDK的Apis或者庫,默認情況下Android平臺集成了很多NDK庫文件涣旨,所以這些文件是沒有必要打包到apk里面去的歪架。直接聲明想要使用的庫名稱即可(猜測:貌似是在Sytem/libs目錄下)。在這里不需要指定庫的路徑霹陡,因為這個路徑已經(jīng)是CMake路徑搜索的一部分和蚪。如示例中使用的是log相關(guān)的so庫。

  • log-lib
    這個指定的是在NDK庫中每個類型的庫會存放一個特定的位置烹棉,而log庫存放在log-lib中

  • log
    指定使用log庫

  • target_link_libraries()
    如果你本地的庫(native-lib)想要調(diào)用log庫的方法攒霹,那么就需要配置這個屬性,意思是把NDK庫關(guān)聯(lián)到本地庫浆洗。

  • native-lib
    要被關(guān)聯(lián)的庫名稱

  • ${log-lib}
    要關(guān)聯(lián)的庫名稱催束,要用大括號包裹,前面還要有$符號去引用伏社。

實際上抠刺,我們可以自己創(chuàng)建CMakeLists.txt文件,而且路徑不受限制摘昌,只要在build.gradle中配置externalNativeBuild.cmake.path來指定該文件路徑即可速妖。

說明

AS2.2版本以后不會再創(chuàng)建jin文件夾,而創(chuàng)建的是cpp文件夾


總結(jié)

Android Studio2.2以上版本進行JNI開發(fā)第焰,只需要在新建項目的時候勾選 Include C++ Support選項买优,AS會自動幫我們搭建好JNI開發(fā)環(huán)境,我們只需要改成我們需要的文件名即可挺举。相比低版本的各種配置杀赢,是簡單方便了很多。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湘纵,一起剝皮案震驚了整個濱河市脂崔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梧喷,老刑警劉巖砌左,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異铺敌,居然都是意外死亡汇歹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門偿凭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來产弹,“玉大人,你說我怎么就攤上這事弯囊√瞪冢” “怎么了胶果?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斤斧。 經(jīng)常有香客問我早抠,道長,這世上最難降的妖魔是什么撬讽? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任蕊连,我火速辦了婚禮,結(jié)果婚禮上锐秦,老公的妹妹穿的比我還像新娘咪奖。我一直安慰自己,他們只是感情好酱床,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著趟佃,像睡著了一般扇谣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闲昭,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天罐寨,我揣著相機與錄音,去河邊找鬼序矩。 笑死鸯绿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的簸淀。 我是一名探鬼主播瓶蝴,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼租幕!你這毒婦竟也來了舷手?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤劲绪,失蹤者是張志新(化名)和其女友劉穎男窟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贾富,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡歉眷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颤枪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汗捡。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖汇鞭,靈堂內(nèi)的尸體忽然破棺而出凉唐,到底是詐尸還是另有隱情庸追,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布台囱,位于F島的核電站淡溯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏簿训。R本人自食惡果不足惜咱娶,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望强品。 院中可真熱鬧膘侮,春花似錦、人聲如沸的榛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夫晌。三九已至雕薪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晓淀,已是汗流浹背所袁。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凶掰,地道東北人燥爷。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像懦窘,于是被迫代替她去往敵國和親前翎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • 用兩張圖告訴你奶赠,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料鱼填? 從這篇文章中你...
    hw1212閱讀 12,723評論 2 59
  • 向您的項目添加 C 和 C++ 代碼 本文內(nèi)容 下載 NDK 和構(gòu)建工具 創(chuàng)建支持 C/C++ 的新項目 構(gòu)建和運...
    會飛的大象_閱讀 3,779評論 0 3
  • 昨晚告誡自己一定不可以熬夜晚睡,強制自己10點關(guān)燈睡覺毅戈。今早6點半自然醒苹丸,神清氣爽,把要做的的事在早上完成不是更好...
    KellyWei閱讀 154評論 0 0
  • 琳經(jīng)過一夜的思考苇经,決定把玉叫過來商量一下赘理。她跟玉直接了當?shù)恼f,現(xiàn)在自己有個機會可以重新返回珠海扇单,老板承諾加薪商模,畢竟...
    碎花紛飛閱讀 290評論 1 2