前提:
NDK環境已經搭建好,
windows下需要安裝cygwim
android studio指向正确的ndk
1、建立一個Android項目, 選擇Empty Activity
2、在MainActivity中定義Native方法
在static語句塊中先加載so庫,這時Android Studio會報錯,先忽略
package com.cxq.jniexample;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("JNI",printHello());
}
// 新定義的native方法,意思是該方法的具體實作交給c語言實作
public native String printHello();
// 加載libprintHello.so動态庫,但是我們在加載時必須去掉lib和字尾
static {
System.loadLibrary("printHello");
}
}
3、建立jni檔案夾,以及.c/.cpp檔案和.h檔案
将視圖切換至Project下,在app\src\main\目錄下建立jni檔案夾
在jni檔案夾下建立c檔案和h檔案
編輯.c檔案如下:
// 引入頭檔案
#include <stdio.h>
#include <jni.h>
#include "printHello.h"
// 定義在MainActivity.java類中的printHello對應的C語言函數
jstring Java_com_cxq_jniexample_MainActivity_printHello(JNIEnv* env, jobject obj){
char* str = "this hello is from jni";
// 調用 jni.h中定義的建立字元串函數
jstring string = (*(*env)).NewStringUTF(env, str);
return string;
}
說明
1、jstring是方法傳回值類型,我們可以把jstring看成是java中String跟C語言中char*類型的一個中間轉換類型,
2、方法的命名規則
Java_[pkgName]_[className]_[funcName]
pkgName:你的包名,但是不能含".",将其替換為“_”
className:用到native方法的類名
funcName:native方法名
3、方法的形參有兩個是必須的也就是不管java中的方法是否有形參,但是C語言中對應的方法必須有JNIEnv* env,和jobject obj,
如果java方法中還用其他形參,那麼在C語言中嚴格按照順序排在jobject obj參數的後面即可。
至此,Android Studio的部分已經準備完畢。
4、使用NDK編譯生成hello.so檔案
首先so檔案是根據mk檔案生成的,是以我們需要先準備好mk檔案,友善起見,我們直接從NDK安裝目錄的sample/hello-jni/jni目錄複制檔案Android.mk和Application.mk
Android.mk的修改
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := printHello
LOCAL_SRC_FILES := printHello.c
include $(BUILD_SHARED_LIBRARY)
說明:
我們隻需要修改LOCAL_MODULE和LOCAL_SRC_FILES兩個參數即可。
LOCAL_MODULE參數是指定編譯後的目标檔案的名稱,其實編譯好的目标檔案名為libhello.so,
LOCAL_SRC_FILES指定了要編譯的源檔案。
Application.mk的修改
通過修改Application.mk檔案來指定生成的動态庫的類型:
如按以的修改則隻會生成一種動态庫:
# Build both ARMv5TE and ARMv7-A machine code.
APP_ABI := armeabi x86
為了友善,也可以指定所有類型
APP_ABI := all
下一步使用cygwin(windows)或則終端進入到工程的jni目錄
輸入:
${NDK}/ndk-build.cmd
這一步的前提是你已經配置好了NDK的環境
這樣so檔案會在libs目錄下生成
修改jni的庫目錄
将app->src->main->libs改成app->src->main->jniLibs
注意:每次運作後ndk-build後,都需要修改這個目錄名,否則對動态庫的修改不會生效;
修改 gradle->gradle.properties
在檔案的最末行添加:
android.useDeprecatedNdk=true
最後運作app,就能出現來自c檔案的字元串了。