Android JNI與NDK學(xué)習(xí)(二)


實(shí)戰(zhàn)演練?

? ? ? 在我們實(shí)戰(zhàn)JNI與NDK時(shí),有兩種方式在編譯.so文件
? ? ? (1)一種是編譯生成 .h頭文件 編寫C/C++文件、Android.mk文件 使用ndk命令來編譯生成 .so文件
? ? ? (2)一種是使用AS下CMake編程自動(dòng)生成 .so文件(這種比較方便)

? ? ? 我們重點(diǎn)講一下第一種 來共同的學(xué)習(xí)一下從JNI到NDK的過程

一、NDK編譯 .so

(1)第一步我們新建一個(gè)項(xiàng)目 新建一個(gè)JniUtils類在JniUtils里面寫native函數(shù),寫完函數(shù)重新build一下或者運(yùn)行一下都o(jì)k

編寫native函數(shù)

(2)將我們的工程目錄從Android目錄下切換到project目錄下
在app的build/intermediates目錄下有個(gè)classes有編譯生成的class文件
(app-->build-->intermediates-->clsasses-->debug-->我們的包名-->JniUtils.class)
使用Terminal 命令工具 進(jìn)入debug目錄下 使用命令javah -jni com.hyperx.jnitestdemo.JniUtils?

編譯生成的class文件

我們看到在debug目錄下會(huì)生成com_hyperx_jnitestdemo_JniUtils.h頭文件? 這個(gè)名字比較長 可以改個(gè)短一點(diǎn)的

編譯 .h 頭文件

(3)在app的main目錄下我們新建一個(gè)jni文件夾,將剛才的 .h頭文件復(fù)制過來 接著要在jni目錄下新建一個(gè)c或者c++文件 都可以
? ? ? ? ? ps.這里要注意一下:c/c++文件中要include我們剛才生成的 .h 頭文件

jni.c文件

(4)接下來就是Android.mk文件? 這里注意一下? 命名一定要規(guī)范
LOCAL_MODULE:? ? 指向的是你將要打包好的.so庫的名字
LOCAL_SRC_FILES:指向的是你寫好的C文件(我這里應(yīng)該是jni.c文件)這個(gè)C文件你可以理解為是一個(gè)目錄

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS :=-llog

LOCAL_MODULE := test

LOCAL_SRC_FILES := jni.c

include $(BUILD_SHARED_LIBRARY)

(5)還有一個(gè)就是Application.mk文件? 這里可以指定你要打包so文件所對(duì)應(yīng)的的平臺(tái),因?yàn)槲疫@里只使用armeabi-v7a? 所以只輸出了一種
輸出全部 改成 all 即可

APP_ABI := all

Application.mk

(6)接下來就是ndk編譯打包.so文件了
? ? ? ? ?我們還是使用窗口命令進(jìn)入main目錄下的jni文件下使用 ndk-build命令即可
? ? ? ? ?ps: 1. 需要進(jìn)入jni目錄下使用ndk命令?
? ? ? ? ? ? ? ?2.我這里只輸出了armeabi-v7a架構(gòu)的so文件? 大家在Application.mk文件中改成all 重新編譯即可生成各個(gè)架構(gòu)的.so文件
? ? ? ? ? ? ? ?3.這里有個(gè)警告————> ndk編譯支持Android的最小版本是16 大家記得改一下

ndk-build

(7)大家重新切換到project視圖下的main目錄,我們可以看到多出來兩個(gè)文件夾? (libs,obj),點(diǎn)開看一下? libs目錄下已經(jīng)有我們打包好的.so庫了,我們把libs下對(duì)應(yīng)架構(gòu)目錄的so拷貝出來就可以使用了,到此我們的ndk工作已經(jīng)完成。(這兩個(gè)文件夾都是編譯產(chǎn)生的,拷貝完后 都可以刪除? 對(duì)項(xiàng)目沒有影響?)

libs,obj

(8)關(guān)于jni的與java的調(diào)用以及return
? ? ? ? ? 我們?cè)趍ain目錄下新建一個(gè)jniLibs目錄 將我們剛才打包好的armeabi-v7a版本的so庫拷貝過去
? ? ? ? ? ps:在build.gradle中我們要指定一下需要使用的cpu架構(gòu)

build.gradle

這里我要load一下so庫? ?這里的 "test" 就是我們?cè)贏ndroid.mk中指定的so的名字?

JniUtils

做一下小測(cè)驗(yàn) 給TextView重新復(fù)制

MainActivity

這里我們可能會(huì)報(bào)錯(cuò)

error

這個(gè)問題主要是因?yàn)锳ndroid studio以前使用ndkCompile后來廢棄掉了,Android-Terminal-Emulator沒有最近沒有更新的緣故。
解決:在build.gradle中的buildTypes加如下幾行代碼? 重新sync一下

sourceSets {
? ? ? ?main {
? ? ? ? ? ? ? jni.srcDirs = []
? ? ? ? }
}

解決


運(yùn)行結(jié)果如下:

success.jpg

二、Android studio 之CMake編程

在我們使用cmake編譯 .so 庫時(shí)我們需要簡(jiǎn)單配置一下cmake環(huán)境
打開AS的SDK manager ——sdk tools 選中對(duì)應(yīng)版本的cmake(注意這里沒有cmake選項(xiàng)的同學(xué),要選擇AS的64位重新啟動(dòng))

cmake

在cmake 下載完 同步以后我們就可以新建項(xiàng)目了
?之前我們?cè)谑褂肁S創(chuàng)建項(xiàng)目的時(shí)候一直沒用過下面兩個(gè)勾選項(xiàng),也沒做過深入了解 現(xiàn)在知道了 是用于Android開發(fā)NDK項(xiàng)目使用的

ndk

在向?qū)У?b>Customize C++ Support部分,您可以使用下列選項(xiàng)自定義項(xiàng)目:
C++ Standard:使用下拉列表選擇您希望使用哪種 C++ 標(biāo)準(zhǔn)。選擇Toolchain Default會(huì)使用默認(rèn)的 CMake 設(shè)置。
Exceptions Support:如果您希望啟用對(duì) C++ 異常處理的支持,請(qǐng)選中此復(fù)選框。如果啟用此復(fù)選框,Android Studio 會(huì)將 -fexceptions 標(biāo)志添加到模塊級(jí) build.gradle文件的 cppFlags中,Gradle 會(huì)將其傳遞到 CMake。
Runtime Type Information Support:如果您希望支持 RTTI,請(qǐng)選中此復(fù)選框。如果啟用此復(fù)選框,Android Studio 會(huì)將 -frtti 標(biāo)志添加到模塊級(jí) build.gradle文件的 cppFlags中,Gradle 會(huì)將其傳遞到 CMake。

項(xiàng)目創(chuàng)建完成后我們運(yùn)行一下? ,看到手機(jī)上面的文字就被修改了

我們還是切換到project視圖下 可以看到cmake自動(dòng)幫我們生成了.so文件
因?yàn)槲疫@里是模擬器 所以他只生成了x86架構(gòu)的so文件

cmake

CMake運(yùn)轉(zhuǎn)流程

1、Gradle 調(diào)用外部構(gòu)建腳本CMakeLists.txt

2、CMake 按照構(gòu)建腳本的命令將 C++ 源文件native-lib.cpp編譯到共享的對(duì)象庫中,并命名為libnative-lib.so,Gradle 隨后會(huì)將其打包到APK中

3、運(yùn)行時(shí),應(yīng)用的MainActivity會(huì)使用System.loadLibrary()加載原生庫。應(yīng)用就是可以使用庫的原生函數(shù)stringFromJNI()。


至此我們jni實(shí)戰(zhàn)Hello word 兩種方式都已實(shí)現(xiàn) 接下來我們學(xué)習(xí)一下JNI函數(shù)與Java函數(shù)之間的相互傳值 (基本數(shù)據(jù)類型,數(shù)組,結(jié)構(gòu)體...)

感覺有用的同學(xué),動(dòng)動(dòng)小手指給個(gè)贊,碼字不易。

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

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