一:前言
? ??近期在學(xué)習(xí)Android NDK,對于怎么使用Android Studio 將C++編譯打包成".so"文件比較好奇,于是就在網(wǎng)上查閱了相關(guān)資料,因?yàn)閯傞_始入門,所以還是花了一些時(shí)間,本文主要記錄相關(guān)操作,希望能幫助跟我一樣初學(xué)習(xí)的小伙伴。
二:使用Android studio兩種方案實(shí)現(xiàn)?
(1)Android Studio 3.6 自帶.so 打包生成
(2)ndk-build 編譯C生成.so文件
三:準(zhǔn)備階段:
? ? 1. 使用Android studio 下載好NDK和CMake
方案一:
? ? 1. 使用Android Studio 創(chuàng)建一個(gè)C++項(xiàng)目(next 默認(rèn)配置創(chuàng)建)
????2. 創(chuàng)建好C++項(xiàng)目可能會報(bào)錯(cuò),需要配置下NDK路徑,如下圖所示
????3. 創(chuàng)建好項(xiàng)目后,點(diǎn)擊 Build -> Make Project
????4. 編譯好項(xiàng)目后,可以在編譯好后的apk文件中查看到打包生成之后的“.so”文件。
????5. 創(chuàng)建C++項(xiàng)目后,會默認(rèn)生成兩個(gè)文件和相關(guān)默認(rèn)配置
????到此使用Android studio 自帶打包".so"文件結(jié)束,接下來主要細(xì)講下,手動(dòng)使用 ndk-build 打包 .so文件
方案二:
????1. 創(chuàng)建一個(gè)類并添加本地
public class NDKStudyTools{
? ? //創(chuàng)建一個(gè)native 方法
? ? public native static StringstringFromJIN();
}
????2. 點(diǎn)擊:Build -> make Project
????3. 構(gòu)建好后,buid 目錄下會生成NDKStudyTools.class 文件(不同as 版本對應(yīng)的詳細(xì)目錄會有不同,不過都在build 目錄下,找下就有)
????4. 創(chuàng)建C++ .h 頭文件
? ? ? ? (1)打開Android Studio ->?Terminal ,使用命令進(jìn)入到項(xiàng)目main目錄:cd app\src\main
????(2)使用命令創(chuàng)建 .h 的頭文件(如果提示“找不到 javah 命令”,需要配置下jdk的環(huán)境變量)
javah -d jni -classpath ...\classes? com.junker.study.c.yagain.NDKStudyTools.class
命令字段介紹:
javah:生成頭文件
-d jni:在當(dāng)前定位到的目錄下創(chuàng)建一個(gè) jni 文件夾
-classpath ...\classes 指定要生成頭文件的字節(jié)碼文件目錄,即生成的 com.junker.study.c.yagain.NDKStudyTools.class 字節(jié)碼目錄?
注意:這個(gè) classes 文件目錄可能太長,輸入麻煩,我們可以找到 debug 文件夾,右鍵 copy path,復(fù)制文件目錄即可
(3)回車之后,會在mian目錄下創(chuàng)建一個(gè)jni文件夾并生成一個(gè) "xxx.h"的頭文件(頭文件命名也是按照包名加字節(jié)碼名的規(guī)范,以下劃線連接)
5. 在jni目錄下創(chuàng)建一個(gè)?.c 文件并實(shí)現(xiàn)com_junker_study_c_yagain_NDKStudyTools.h 頭文件中的本地方法
? ? (1)copy? .h 文件中的native方法到 .c文件中,此時(shí)會有警告,alt+enter 解除警告。
(2)實(shí)現(xiàn)好之后,點(diǎn)擊右上角:sync now 同步下
6. jni 目錄下再次 創(chuàng)建 .mk 文件
????(1)創(chuàng)建?Android.mk 文件并添加配置(注意:不要在文件中添加注釋字符,使用?ndk-build 命令編譯時(shí)會報(bào)錯(cuò))。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=app
LOCAL_SRC_FILES:=ndk_test.c
include $(BUILD_SHARED_LIBRARY)
參數(shù)說明:(注:以下不用拷貝到文件中,此處只做說明)
LOCAL_PATH := $(call my-dir):
? ? 設(shè)置工作目錄,它用于在開發(fā)tree中查找源文件。宏my-dir由Build System提供,會返回Android.mk文件所在的目錄
include $(CLEAR_VARS):
? ? CLEAR_VARS變量由Build System提供。指向一個(gè)指定的GNU Makefile,由它負(fù)責(zé)清理LOCAL_xxx類型文件,但不是清理LOCAL_PATH,所有的編譯控制文件由同一個(gè)GNU Make解析和執(zhí)行,其變量是全局的。所以清理后才能便面相互影響,這一操作必須有。
LOCAL_MODULE:=app:
? ? 模塊必須定義,以表示Android.mk中的每一個(gè)模塊,名字必須唯一且不包含空格,Build System會自動(dòng)添加適當(dāng)?shù)那熬Y和后綴。例如,demo,要生成動(dòng)態(tài)庫,則生成libdemo.so。但請注意:如果模塊名字被定義為libabd,則生成libabc.so。不再添加前綴。
LOCAL_SRC_FILES := ndk_test.c:
? ? 指定參與模塊編譯的C/C++源文件名。不必列出頭文件,build System會自動(dòng)幫我們找出依賴文件。缺省的C++源碼的擴(kuò)展名為.cpp。
include $(BUILD_SHARED_LIBRARY):
? ? BUILD_SHARED_LIBRARY是Build System提供的一個(gè)變量,指向一個(gè)GUN Makefile Script。它負(fù)責(zé)收集自從上次調(diào)用include $(CLEAR_VARS)后的所有LOCAL_xxxxinx。并決定編譯什么類型
? ? 1. BUILD_STATIC_LIBRARY:編譯為靜態(tài)庫
? ? 2. BUILD_SHARED_LIBRARY:編譯為動(dòng)態(tài)庫
? ? 3. BUILD_EXECUTABLE:編譯為Native C可執(zhí)行程序
? ? 4. BUILD_PREBUILT:該模塊已經(jīng)預(yù)先編譯
(2)創(chuàng)建 Application.mk 文件并添加配置(注意:不要在文件中添加注釋字符,使用?ndk-build 命令編譯時(shí)會報(bào)錯(cuò))。
APP_ABI := all
參數(shù)說明:(注:以下不用拷貝到文件中,此處只做說明)
APP_ABI := all
????默認(rèn)生成支持的多種類型.so
示例圖:
7.?生成so庫
(1)?使用 Terminal 命令進(jìn)入到項(xiàng)目jni目錄:cd app\src\main\jni
(2)使用?ndk-build 命令生成 so 庫( 如果提示沒有,需要配置下ndk的環(huán)境變量)
8、使用so庫
(1)為了能加載 app.so 庫,需要在主module下的 build.gradle 文件夾的 android 下添加如下代碼:
sourceSets{
? ? main() {
? ? ? ? jniLibs.srcDirs =['src/main/libs']
? ? ? ? jni.srcDirs =[] //disable automatic ndk-build call, which ignore our Android.mk
? ? }
}
(2)在 NDKStudyTools.java 中加載 so 庫(注:庫名稱不需要寫 libapp,只用寫 app,也就是去掉lib前綴)
public class NDKStudyTools{
? ? // 動(dòng)態(tài)導(dǎo)入 so 庫
? ? static {
? ? ? ? System.loadLibrary("app");
? ? }
? ? //創(chuàng)建一個(gè)native 方法
? ? public native static StringstringFromJIN();
}
(3)驗(yàn)證使用,跑一跑run