1. 程式人生 > >Android Studio NDK JNI 實踐

Android Studio NDK JNI 實踐

環境要求

1 . Android Studio2.2 以上

2.2 以上版本的Android Studio會自動下載ndk-bundle 並配置好ndk路徑

具體步驟

1 . 新建一個專案名字隨意取名,我這邊叫做NDKTest 一路next 直到finish 建立完成。
image
2 . 在專案工程目錄的src/main建立jni目錄,如果有就不要在新建了。
3 . 新建Android.mk檔案 內容如下

LOCAL_PATH       :=  $(call my-dir)
# 設定工作目錄,而my-dir則會返回Android.mk檔案所在的目錄

include              $(CLEAR_VARS)
# 清除幾乎所有以LOCAL——PATH開頭的變數(不包括LOCAL_PATH)
LOCAL_MODULE := hello_jni # 設定模組的名稱,即編譯出來.so檔名 # 注,要和上述步驟中build.gradle中NDK節點設定的名字相同 LOCAL_SRC_FILES := test.cpp # 指定參與模組編譯的C/C++原始檔名 include $(BUILD_SHARED_LIBRARY) # 指定生成的靜態庫或者共享庫在執行時依賴的共享庫模組列表。

4 . 新建Application.mk檔案,內容如下:

APP_ABI := rmeabi x86 mips
# 最常用的APP_ABI欄位:指定需要基於哪些CPU平臺的.so檔案
# 常見的平臺有armeabi x86 mips,其中移動裝置主要是armeabi平臺 # 預設情況下,Android平臺會生成所有平臺的.so檔案,即同APP_ABI := armeabi x86 mips # 指定CPU平臺型別後,就只會生成該平臺的.so檔案,即上述語句只會生成armeabi平臺的.so檔案

5 . 新建test.cpp檔案 內容如下

# include <jni.h>
# include <stdio.h>

extern "C"
{

    JNIEXPORT jstring JNICALL Java_com_lzc_ndktest_MainActivity_getFromJNI(JNIEnv *env, jobject obj ){
       // 引數說明
// 1. JNIEnv:代表了VM裡面的環境,本地的程式碼可以通過該引數與Java程式碼進行操作 // 2. obj:定義JNI方法的類的一個本地引用(this) return env -> NewStringUTF("Hello i am from JNI!"); // 上述程式碼是返回一個String型別的"Hello i am from JNI!"字串 } }

Java_com_lzc_ndktest_MainActivity_getFromJNI 命名規則

  • Java是必寫後接_
  • 中間的com_lzc_ndktest是將應用包名com.lzc.ndktest的.替換成即可後接
  • MainActivity是載入動態庫使用的類檔案
  • getFromJNI 是jni方法的名稱
  • 如果包名中存在_ 則對應的替換成_1

最後三個檔案位置如下圖所示:

image

6 . 定位到jni目錄下 執行ndk-build,完成後在工程目錄的main資料夾下生成libs和obj資料夾,如下圖:
image
將main目錄下的libs資料夾裡面的檔案複製到工程目錄下的libs中。
image
7. 在app的build.gradle檔案中新增如下程式碼:

android{
    ....
 sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
//            jniLibs.srcDir 'src/main/libs'
//            java.srcDirs += 'src/main/jni/src'
//            assets.srcDirs += 'src/main/jni/assets'
        }
    }
....
}

8 . 在MainActivity中新增如下程式碼:

//載入動態庫 不用寫前面的lib 
static {
        System.loadLibrary("hello_jni");
    }
    // 步驟2:定義在JNI中實現的方法
    public native String getFromJNI();

9 . 呼叫事例,如下所示:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView= (TextView) findViewById(R.id.text_hello_jni);
        textView.setText(getFromJNI());

    }

10 . 執行結果圖