1.明確爲何要學習JNI
- JNI是Java Native Interface的縮寫,它提供了若干的API實現了Java和其他語言的通信(主要是C&C++)。從Java1.1開始,JNI標準成爲java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是爲了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他編程語言,只要調用約定受支持就可以了。使用java與本地已編譯的代碼交互,通常會喪失平臺可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬件、操作系統進行交互,或者爲了提高程序的性能。JNI標準至少要保證本地代碼能工作在任何Java 虛擬機環境。
- Java開發要用到JDK,Android開發要用到SDK,那我們在Android中要進行native開發,也要用到它對應的工具包,即NDK。通俗的來講,NDK就是幫助我們可以在Android應用中使用C/C++來完成特定功能的一套工具。 NDK的作用有很多,我們簡單的列舉兩個,比如:
1.首先NDK可以幫助開發者“快速”開發C(或C++)的動態庫。
2.其次,NDK集成了“交叉編譯器”。使用NDK,我們可以將要求高性能的應用邏輯使用C開發,從而提高應用程序的執行效率.
arm結構 :主要在移動手持、嵌入式設備上。我們的手機幾乎都是使用的這種CUP架構。
x86結構 : 主要在臺式機、筆記本上使用。如Intel和AMD的CPU 。
MIPS架構:多用在網關、貓、機頂盒等設備
2.NDK下載:https://developer.android.google.cn/ndk/downloads 根據操作系統選擇
3.as配置ndk:file->Project Structure->SDK Location->Android NdK Location寫入下載解壓後的ndk路徑
4.jni開發流程
- 在MainActivity類中聲明函數jniSay(native關鍵字):
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
public native String jniSay(String str);
public void click(View view) {
System.loadLibrary("JniSay");
String str=jniSay("hello word");
Toast.makeText(this,str,Toast.LENGTH_LONG).show();
}
}
- 在main目錄下新建文件夾jni
- 在jni下新建JniSay.c文件
- 進到main/java裏使用命令:
D:\android\jniTest\app\src\main\java>javah -jni com.zcx.myapplication.MainActivity
- 打開生成的com_zcx_myapplication_MainActivity.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_zcx_myapplication_MainActivity */
#ifndef _Included_com_zcx_myapplication_MainActivity
#define _Included_com_zcx_myapplication_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_zcx_myapplication_MainActivity
* Method: jniSay
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_zcx_myapplication_MainActivity_jniSay
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
- 將下述代碼複製到JniSay.c文件裏
#include<stdlib.h>
#include<jni.h>
JNIEXPORT jstring JNICALL Java_com_zcx_myapplication_MainActivity_jniSay(JNIEnv * env,jstring str){
char* c="I am from c....";
return (**env).NewStringUTF(env,c);
}
jstring對應java中的string類
jstring本質還是void*類型的指針(在jni.h裏申明的所以要導入)
7. 在jni目錄下新建Android.mk (https://developer.android.google.cn/ndk/guides/android_mk)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= JniSay
LOCAL_SRC_FILES:= JniSay.c
#LOCAL_CFLAGS:= -Wall -Wextra -Werror
#LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)
#LOCAL_EXPORT_LDLIBS:= -ldl
include $(BUILD_SHARED_LIBRARY)
- 在jni目錄下新建Application.mk (https://developer.android.google.cn/ndk/guides/application_mk)可選
- 進入jni目錄執行命令:ndk-build JniSay
- 在項目gradle.properties裏添加: android.useDeprecatedNdk=true
- 在app/build.gradle裏的defaultConfig節點添加:
defaultConfig {
applicationId "com.zcx.myapplication"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
moduleName "JniSay"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDir 'libs'
}
}
- 將main/obj/local下的文件複製到 項目/libs下