Android NDK開發之旅15 NDK Eclipse下NDK開發流程

weixin_33809981發表於2017-12-18

###Eclipse下NDK開發流程

先來個Eclipse版本的,後續再上AS版本的。工具的使用不同而已。

###具體流程

  1. 編寫Java層Native方法
  2. javah命令生成標頭檔案
  3. 建立jni目錄
  4. 配置NDK路徑,新增本地支援add native support,配置ADT需要包含的標頭檔案
  5. 實現標頭檔案中定義的函式
  6. 編譯生成.so動態庫
  7. 載入動態庫

下面以建立一個簡單的檔案加密解決APP來作為示範:

####一、編寫Java層Native方法

我們專門建立一個Cryptor類用於檔案的加密解密:

public class Cryptor {

	public static native void cryptFile(String src , String dest);

	public static native void decryptFile(String src , String dest);

}
複製程式碼

這裡寫兩個native方法,分別用於檔案加密解密。

####二、使用javah命令生成對應的標頭檔案

在命令列下,通過cd命令轉到工程的src目錄(程式碼目錄),然後執行以下命令:

javah 完整類名
複製程式碼

就會生成對應的標頭檔案。

####三、建立jni目錄

直接通過Eclipse來建立即可,然後把我們剛剛生成的標頭檔案放進去。

####四、配置NDK路徑,新增本地支援add native support,配置ADT需要包含的標頭檔案

沒有配置NDK路徑的需要先配置一下:

Windows-->Preference-->Android-->NDK:

新增native support,右擊專案,選擇Android Tools,選擇add native support,然後彈出下面的介面,輸入lib的名字,字首系統預設為lib。

然後會在jni目錄自動生成一些檔案:

其中Application.mk是我們自己新增的,用於指定輸出什麼架構的so動態庫檔案,Application.mk如下:

# armeabi armeabi-v7a arm64-v8a mips mips64 x86 x86_64
APP_ABI := armeabi
複製程式碼

其中第一行是註釋。

配置ADT中需要包含的NDK標頭檔案:右擊工程-->屬性-->C/C++常規-->路徑和符號,新增NDK的以下目錄:

G:\android-ndk-r10\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.9\include
G:\android-ndk-r10\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.9\include-fixed
G:\android-ndk-r10\platforms\android-L\arch-arm\usr\include
複製程式碼

######注意:筆者的版本可能跟你的版本不一樣,不過大同小異

配置好的圖如下:(某些目錄是後來生成的)

####五、實現標頭檔案中定義的函式

我們在crypt.c中實現吧,本來是cpp檔案的,我們目前先改為c實現:

#include "com_example_ndk_file_crypt_utils_Cryptor.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char password[] = "I AM MI MA";

JNIEXPORT void JNICALL Java_com_example_ndk_1file_1crypt_utils_Cryptor_cryptFile(
		JNIEnv * env, jclass jclz, jstring src, jstring dest) {

	const char* c_src = (*env)->GetStringUTFChars(env, src, NULL);
	const char* c_dest = (*env)->GetStringUTFChars(env, dest, NULL);

	FILE* f_read = fopen(c_src, "rb");
	FILE* f_write = fopen(c_dest, "wb");

	//判斷檔案是否正確開啟
	if (f_read == NULL || f_write == NULL ) {
		printf("file open field");
		return;
	}

	//一次讀取一個字元
	int ch;
	int i = 0;
	int pwd_len = strlen(password);
	while ((ch = fgetc(f_read)) != EOF) {
		//通過異或運算進行加密
		fputc(ch ^ password[i % pwd_len], f_write);
		i++;
	}

	//關閉檔案
	fclose(f_read);
	fclose(f_write);

}

JNIEXPORT void JNICALL Java_com_example_ndk_1file_1crypt_utils_Cryptor_decryptFile(
		JNIEnv * env, jclass jclz, jstring src, jstring dest) {

	const char* c_src = (*env)->GetStringUTFChars(env, src, NULL);
	const char* c_dest = (*env)->GetStringUTFChars(env, dest, NULL);

	FILE* f_read = fopen(c_src, "rb");
	FILE* f_write = fopen(c_dest, "wb");

	//判斷檔案是否正確開啟
	if (f_read == NULL || f_write == NULL ) {
		printf("file open field");
		return;
	}

	//一次讀取一個字元
	int ch;
	int i = 0;
	int pwd_len = strlen(password);
	while ((ch = fgetc(f_read)) != EOF) {
		//通過異或運算進行加密
		fputc(ch ^ password[i % pwd_len], f_write);
		i++;
	}

	//關閉檔案
	fclose(f_read);
	fclose(f_write);

}
複製程式碼

然後記得配置Android.mk檔案,把LOCAL_SRC_FILES的值改為crypt.c(原來是cpp)。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := crypt
LOCAL_SRC_FILES := crypt.c

include $(BUILD_SHARED_LIBRARY)
複製程式碼

####六、編譯生成.so動態庫

直接make project一下即可。

####七、載入動態庫

通過System.loadLibrary方法載入動態庫.so檔案,注意不用寫lib字首,系統會預設新增。

public class Cryptor {

	static {
		//載入動態庫.so檔案,注意不用寫lib字首,系統會預設新增
		System.loadLibrary("crypt");
	}

	public static native void cryptFile(String src , String dest);

	public static native void decryptFile(String src , String dest);

}
複製程式碼

剩下的就在Android佈局中寫兩個按鈕,測試一下即可,記得加上SD卡訪問許可權:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
複製程式碼

最後,說明一下,如果要適配所有平臺,需要修改Application.mk為:

APP_ABI := armeabi armeabi-v7a arm64-v8a mips mips64 x86 x86_64
複製程式碼

由於生成的過程需要交叉編譯,速度非常慢,大概五分鐘左右,因此,如果c程式碼沒有改變的話,我們可以通過下面的配置,不編譯c程式碼:

把兩個勾去掉即可。

如果覺得我的文字對你有所幫助的話,歡迎關注我的公眾號:

我的群歡迎大家進來探討各種技術與非技術的話題,有興趣的朋友們加我私人微信huannan88,我拉你進群交(♂)流(♀)

相關文章