最近項目要做圖片的加解密工作,從老闆給的代碼來看像是AES,但也有區別,所以也沒有采用java那個封裝好的包。給我的是C代碼,之前android留了接口,所以還是採用Jni方式直接調吧。
1、先做了一個本地解密的demo,直接把圖片用加密工具,加密。然後存到手機SD卡上。
2、準備工作,因爲是在windows環境下做的,所以使用的是cygwin,NDK版本是R8,比較老了。配置方法網上搜一下就有,主要配置NDK路徑。工程文件如下
3、把老闆給的代碼AES.C AES.h 複製到工程
4、編寫mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_MODULE := AES
LOCAL_SRC_FILES := AESAndroid.c AES.c
include $(BUILD_SHARED_LIBRARY)
5.編寫接口函數 即AESandroid.c
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include "memory.h"
#include <android/log.h>
#define LOG_TAG "AESAndroid.c"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
/*********************解密*********************/
JNIEXPORT jint JNICALL Java_androidJni_MyAESAlgorithm_fileDecrypt(JNIEnv *env,
jclass thiz, jstring srcPath, jstring key, jstring resultPath,jint encrypt_type) {
const char * sPath = (*env)->GetStringUTFChars(env,srcPath, NULL);
const char * sKey = (*env)->GetStringUTFChars(env,key, NULL);
const char * rPath = (*env)->GetStringUTFChars(env,resultPath, NULL);
LOGI(sPath);
LOGI(sKey);
int len_skey = strlen(sKey);
FILE* file = NULL;
file = fopen(sPath, "rb");
if (file == NULL) {
LOGI("file is not ");
return 131111;
}
fclose(file);
file = NULL;
unsigned char bKey[17] = { '\0' };
unsigned char bIV[17] = { '\0' };
memcpy(bKey, sKey, 16);
memcpy(bIV, sKey + 16, 16);
int flag = fileDecrypt(sPath, bKey, bIV, encrypt_type);
(*env)->ReleaseStringUTFChars(env,resultPath, rPath);
(*env)->ReleaseStringUTFChars(env,key, sKey);
(*env)->ReleaseStringUTFChars(env,srcPath, sPath);
return flag;
}
#ifdef __cplusplus
}
#endif
需要說明的是,文件頭是可以自動生成的,函數名規則就是java_包名_類名_函數名。在Jni調用中C和C++還是有區別的 避免不必要的錯誤 最好不要混用,如過編譯的是.cpp
(*env)要寫成env,如果引的頭文件是stido.h, 就別char *content=new char[iDataLen]了,用char *content = (char*)malloc(sizeof(char)*iDataLen);等等吧,我這C還是C89標準
在for循環裏初始化變量都報錯。
6.生成.so庫
簡單說一下編譯方法吧。啓動cgywin
進入Jni文件夾,我的工程在E盤編程練習文件夾裏
然後輸入$NDK/ndk-build 就可以編譯.so庫了
7.java層寫個類封裝一下
public class MyAESAlgorithm
{
public synchronized static native int fileDecrypt(String srcPath, String key, String resultPath,int encrypt_type);
static
{
System.loadLibrary("AES");
}
}
8.做好參數,傳入即可
<pre name="code" class="java">private void testAES() {
String Key = "0123456789abcdef0123456789abcdef";
String srcPath = "/mnt/sdcard/UCDownloads/d.jpg";
String resultPath="flie:///mnt/sdcard/UCDownloads/e.jpg";
System.out.println("------------密鑰----------------");
System.out.print(Key);
MyAESAlgorithm.fileDecrypt(srcPath, Key, resultPath,1);
System.out.println();
System.out.println("------------ END ----------------");
}