使用Android Studio開發第一個NDK程序

NDK(Native Development Kit),是用於在 Android 應用中嵌套本地代碼的工具集,現在 Android 開發最常用的工具就是 Android Studio 了,我花了一個整天的時間,才搞定了它,其中遇到了好多問題。在這裏整理出來,供大家參考學習,避免大家入這樣的坑。

項目地址:JNITest

Android Studio版本:Android Studio2.3

NDK版本:android-ndk-r19c

第一步:給 Android Studio 配置 NDK

選擇SDK Manage—SDK Tools,勾選NDK和LLDB,然後點擊Apply。

在這裏插入圖片描述
NDK我在外面已經下載完畢,所以這裏沒有勾選。

接下來等待下載安裝即可,下載完成後,打開File—Other Settings—Default Project Structure,可以看到NDK的默認安裝路徑。配置完成。

NDK目錄結構:

build/tools:linux的批處理文件
platforms:編譯C代碼需要使用的頭文件和類庫
prebuilt:預編譯使用的二進制可執行文件
source:ndk的源碼
toolchains:工具鏈
ndk-build.cmd:編譯打包C代碼的一個指令

接下來寫程序。

注意: 如果配置過程中出現can’t found mipsel-linux-android…,這是因爲NDKr17c以上沒有了mipsel包,想要消除這個錯誤,可以更新AS或者將舊版本的mipsel包拷貝到NDK文件夾中的toolchains文件夾下(項目mips下)。

從第二步開始就是相當於屬於 JNI(Java Native Interface | Java 本地接口) 開發的基礎流程,因爲 NDK 是基於 JNI 。

第二步:新建一個項目,創建一個JNITest.java的類

	public class JNITest {

		//創建一個 native 方法
		public native static String get();
	}

注意: 如果你創建的 get() 方法是紅色的,並且有這樣的提示:Cannot resolve corresponding JNI function Java_com_example_akon_jnitest_JNITest_get more…

解決辦法: File—Settings—Plugins,找到Android NDK Support,把後面的勾去掉,點擊OK,然後Restart。

當然,如果你沒有這種情況就不用管。

第三步:創建C語言文件,創建so庫。

點擊Build—Make Project,生成JNITest.class文件。然後使用 Project 方式查看當前項目,在當前目錄下可以看到你的 JNITest.class 文件

在這裏插入圖片描述

打開 Android Studio 的 Terminal 到 移動到 app/src/main 目錄下。

使用 javah -d jni -classpath D:\Android\JNITest\app\build\intermediates\classes\debug com.example.yhj.jnitset.JNITest 命令創建 .h 的頭文件

javah:生成頭文件    

-d jni:當前目錄下創建一個 jni 文件夾    

-classpath .../debug 指定要生成頭文件的字節碼文件目錄,即我們剛剛的 JNITest.class 的目錄 

com.example.yhj.jnitset.JNITest 是 JNITest 文件的包名加上字節碼文件的名稱
注意:這個 debug 文件目錄可能太長,輸入麻煩,我們可以找到 debug 文件夾,右鍵 copy path,複製文件目錄即可。

現在我們可以看到 app/src/main 目錄下有一個 jni 文件夾,裏面有一個 com_example_yhj_jnitset_JNITest.h 的頭文件,就是我們生成的頭文件,頭文件命名也是按照包名加字節碼名的規範,以下劃線連接。

然後在jni目錄下創建一個File命名爲test.c,選擇c爲後綴。

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

	//導入我們創建的頭文件

	#include "com_example_yhj_jnitset_JNITest.h"

	JNIEXPORT jstring JNICALL Java_com_example_yhj_jnitset_JNITest_get(JNIEnv *env, jclass jclass){

	//返回一個字符串
	 	return (*env)->NewStringUTF(env,"This is my first NDK Application");
	}

下面的這個方法使我們從頭文件中複製過來的。

在這裏插入圖片描述

然後修改了參數,給了返回值。

然後我們在 jni 目錄下創建兩個 .mk 文件:

一個是 Android.mk

關於Android.mk語法參閱:Android.mk的用法和基礎

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := JNITest
LOCAL_SRC_FILES := test.c
include $(BUILD_SHARED_LIBRARY)

一個是 Application.mk:

APP_ABI := all //根據不同的NDK版本,APP_ABI := all僅能生成當前版本支持的ABI信息庫文件

然後我們需要生成so庫:

打開 Terminal,到 app/src/main/jni 目錄下,使用 ndk-build 命令生成 so 庫:

接着打開 app/src/main/libs 就可以看見我們生成的 so 庫了。

爲了防止 so 庫兼容錯誤,在 gradle.properties 最後一行添加:

android.useDeprecatedNdk=true

爲了讓項目能夠找到我們的 so 庫,在 build.gradle 文件夾的 android 下添加:

sourceSets {
    main() {
        jniLibs.srcDirs = ['src/main/libs']
        jni.srcDirs = [] //屏蔽掉默認的jni編譯生成過程
    }
}

然後我們在 JNITest.java 中動態導入 so 庫,不需要寫 libJNITest,只用寫 JNITest(掐頭去尾):

public class JNITest {

	static {
    System.loadLibrary("JNITest");
	}

	//生成一個native方法
	public native static String get();
}

然後我們在 MainActivity 中打印 JNITest 的 get() 方法獲取到的 String 值:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.e("message",JNITest.get());
}

}

然後運行,查看日誌,搜索 Message:

在這裏插入圖片描述

然後我們就查看到了我們獲取的 String 了,“This is my first NDK Application”,就是我們在 C 語言文件中所返回的字符串。

總結: JNI(Java Native Interface|||Java本地開發接口)是一個協議,用來溝通Java代碼和外部的本地代碼。可實現Java代碼與C/C++代碼的互相調用。NDK(Native Develop Kits)是使用JNI的編譯打包工具。使用NDK,我們可以將要求高性能的應用邏輯使用C開發,從而提高應用程序的執行效率,我們可以將需要保密的應用邏輯使用C開發。畢竟,Java包都是可以反編譯的。

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