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 . 運行結果圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章