AndroidStudio上進(jìn)行NDK開(kāi)發(fā)

動(dòng)態(tài)注冊(cè)JNI函數(shù)

其實(shí)NDK開(kāi)發(fā)具體操作在NDK官網(wǎng)Guides中已經(jīng)有了很詳細(xì)的介紹。。這里主要記錄一下我自己的操作過(guò)程和遇到的坑

1、準(zhǔn)備工作

先配置好AndroidStudio的NDK環(huán)境

  1. NDK官網(wǎng)下載合適的NDK版本
  2. 下載好NDK開(kāi)發(fā)包之后解壓到自己指定的目錄中
  3. 設(shè)置AndroidStudio 的NDK路徑,有兩種設(shè)置方法
  1. 可以通過(guò)local.properties文件設(shè)置
local.properties
local.properties配置內(nèi)容
  1. 也可以通過(guò)AndroidStudio來(lái)設(shè)置
AS菜單欄
Project Structure
2、項(xiàng)目配置

添加C/C++ 代碼有兩種情況,一種是有.so文件,第二種是有源碼需要編譯出.so

2.1 已有.so 文件的情況

2.1.1 把.so文件添加到工程路徑app/libs 下對(duì)應(yīng)的CPU架構(gòu)的文件夾下

.so工程中的位置

2.1.2 然后在build.gradle中配置jni庫(kù)的尋找路徑

sourceSets.main { jniLibs.srcDirs = ['libs']}

build.gradle中jni庫(kù)的尋找路徑配置

當(dāng)然這里就可以指定其他路徑,然后把.so文件放到對(duì)應(yīng)路徑下的CPU架構(gòu)的文件夾下

注意 之前看一篇文章說(shuō)libs是AndroidStudio默認(rèn)的搜索路徑,所以我就沒(méi)到build.gradle中添加配置,導(dǎo)致jni調(diào)用的函數(shù)一直沒(méi)有找到而拋出異常。不知道是不是我自己的操作問(wèn)題,不過(guò)加上配置就都正常了

2.2 有源碼,需要編譯出.so

編譯.so有兩種方式,第一種通過(guò)手動(dòng)執(zhí)行命令編譯出.so文件,具體可以看另一篇文章ndk-build生成.so

第二種是通過(guò)添加相應(yīng)配置,讓AndroidStudio來(lái)編譯源碼

#######2.2.1 創(chuàng)建放源碼的jni文件夾

源碼存放的默認(rèn)位置為app/src/main/jni中

jni文件夾路徑

如果工程中沒(méi)有這個(gè)文件夾,可以通過(guò)菜單創(chuàng)建,當(dāng)然也可以直接在這個(gè)路徑下創(chuàng)建一個(gè)叫jni的文件夾

創(chuàng)建jni文件夾菜單

還可以自定義目錄,然后在build.gradle中做一個(gè)資源路徑指定即可(不過(guò)這種方式我沒(méi)驗(yàn)證過(guò),后面試了一下好像是錯(cuò)的):

指定jni文件夾配置

#######2.2.2 添加編譯相關(guān)的配置

將源碼放到2.2.1中創(chuàng)建的jni目錄下,并在該目錄下添加編譯需要的配置文件,主要就是Android.mk和Application.mk,這兩個(gè)配置文件和ndk-build生成.so中提到的是相同的,相關(guān)配置西甲誒可以看NDK官網(wǎng)build教程

也可以通過(guò)在 build.gradle中添加NDK的編譯配置,這樣就不用添加Android.mk和Application.mk了


build.gradle添加NDK編譯配置
ndk{
  moduleName "jniLib"     // 模塊名,編譯出來(lái)的 .so 文件 

  // 指定編譯平臺(tái)
  // 更多平臺(tái)信息 參見(jiàn)https://developer.android.com/ndk/guides/abis.html#sa
  abiFilters "armeabi", "armeabi-v7a", "x86"

\* Other ndk flags configurable here are
 * cppFlags.add("-fno-rtti")
 * cppFlags.add("-fno-exceptions")
 * ldLibs.addAll(["android", "log"])
 * stl       = "system"
 */
}

使用gradle的好處是,自動(dòng)編譯生成apk文件,并且把相關(guān)的.so文件打包到apk安裝包中

3、Java代碼中調(diào)用
package com.zzl.injecthost;

public class NdkJniUtils {
  static{
      System.loadLibrary("jniLib");
  }

  public native String StringFromJNI();
}

這里System.loadLibrary("jniLib"); 這個(gè)jniLib即為在2.2.2中build.gradle內(nèi)配置的moduleName

Java中聲明jni函數(shù)
NdkJniUtils jni = new NdkJniUtils();
textView.setText(jni.StringFromJNI());
jni函數(shù)調(diào)用

這里有個(gè)注意點(diǎn)
NDK下的C/C++函數(shù)和Java橋接的函數(shù)命名是有約束的,規(guī)則如下:

Java_PackageName_ClassName_MethodName

例如下面,我有個(gè)NdkJniUtils類在com.zzl.injecthost中,在這個(gè)類中聲明一個(gè)native的jni函數(shù),則C/C++對(duì)應(yīng)的函數(shù)的簽名應(yīng)該為:

Java_com_zzl_injethost_NdkJniUtils_StringFromJNI(JNIEnv *env, jobject obj)
{ 
   return (*env)->NewStringUTF(env, "Hello from JNI !");
}
最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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