前提:
NDK環境已經搭建好,
windows下需要安裝cygwim
android studio指向正確的ndk
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文件的字符串了。