要使用NDK首先要了解NDK到底是什么?
(英語(yǔ):native development kit,簡(jiǎn)稱NDK)是一種基于原生程序接口的軟件開發(fā)工具。通過此工具開發(fā)的程序直接以本地語(yǔ)言運(yùn)行,而非虛擬機(jī)。因此只有java等基于虛擬機(jī)運(yùn)行的語(yǔ)言的程序才會(huì)有原生開發(fā)工具包。[維基百科]
NDK是一系列工具的集合
NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動(dòng)態(tài)庫(kù),并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開發(fā)者的幫助是巨大的.
NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺(tái)、ABI等差異,開發(fā)人員只需要簡(jiǎn)單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。
NDK可以自動(dòng)地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作。
為什么要使用?
1、代碼的保護(hù)。由于apk的java層代碼很容易被反編譯,而C/C++庫(kù)反匯難度較大。能夠阻擋一定的開發(fā)者進(jìn)行逆向。
2、可以方便地使用現(xiàn)存的開源庫(kù)。大部分現(xiàn)存的開源庫(kù)都是用C/C++代碼編寫的。
3、提高程序的執(zhí)行效率。將要求高性能的應(yīng)用邏輯使用C開發(fā),從而提高應(yīng)用程序的執(zhí)行效率。
4、便于移植。用C/C++寫得庫(kù)可以方便在其他的嵌入式平臺(tái)上再次使用。
NDK和CMake 的下載和安裝
打開android studio 找到Sdk管理器,進(jìn)行下載安裝即可。
下面開發(fā)正式開發(fā):
1、創(chuàng)建jni文件夾用來存放調(diào)用C++相關(guān)的文件,有兩個(gè)配置文件和頭文件以及源文件
配置文件:Android.mk
作用:命令行cd到src/main/jni文件夾下,使用命令ndk-build生成.so文件,這里邊定義了生成.so庫(kù)的文件名、指定編譯的c++源文件和頭文件,用于向構(gòu)建系統(tǒng)描述源文件和共享庫(kù),讓ndk去按照指定的方式編譯c++源文件和頭文件。
編譯目標(biāo)目錄聲明
LOCAL_PATH:=$(call my-dir) ? LOCAL_PATH需要編譯源文件所在的目錄,$(call my-dir)使用宏定義,my-dir是返回值對(duì)應(yīng)Android.mk所在的目錄。
重置全局變量
include $(CLEAR_VARS) ? ? ? ? ?CLEAR_VARS變量指向特殊 GNU Makefile, 可為您清除許多LOCAL_XXX變量.不包括LOCAL_PATH因?yàn)橄到y(tǒng)在單一 GNU Make 執(zhí)行環(huán)境(其中所有變量都是全局的)中解析所有構(gòu)建控制文件. 在描述每個(gè)模塊之前, 必須聲明(重新聲明)此變量
LOCAL_MODULE:=secretkey 指定模塊的名稱
LOCAL_MODULE, 指定模塊的名稱,唯一且不含空格, 之后會(huì)編譯出librecorder-jni.so, 如果模塊名已包含前綴lib, 則不會(huì)自動(dòng)添加lib前綴.
LOCAL_SRC_FILES:=secretkey.cpp secretkey.h 指定編譯c++源文件和頭文件
待編譯的源文件
LOCAL_SRC_FILES,指定源文件列表, 多個(gè)文件使用空格分割.可以使用相對(duì)文件路徑(指向 LOCAL_PATH)和絕對(duì)文件路徑
LOCAL_LDLIBS :=-llog 打印log
include $(BUILD_SHARED_LIBRARY)整合
BUILD_SHARED_LIBRARY變量指向GNU Makefile腳本, 用于收集您自最近 include 后在 LOCAL_XXX 變量中定義的所有信息.其實(shí)就是讓上一次include到這里之間的內(nèi)容生效
編譯模塊輸出名稱
LOCAL_MODULE_FILENAME, 真正的庫(kù)輸出文件名. 如果不喜歡系統(tǒng)自動(dòng)生成的文件名, 可以指定這個(gè)值
LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo
Application.mk
此文件枚舉并描述您的應(yīng)用需要的模塊。Android.mk有效的前提是依靠該文件的保證位于jni的目錄下.包含下面幾個(gè)方面的內(nèi)容:
用于針對(duì)特定平臺(tái)進(jìn)行編譯的 ABI。
工具鏈。
要包含的標(biāo)準(zhǔn)庫(kù)(靜態(tài)和動(dòng)態(tài) STLport 或默認(rèn)系統(tǒng))。
APP_STL := stlport_static 靜態(tài)標(biāo)準(zhǔn)庫(kù)
Android NDK 默認(rèn)使用的是最小支持的C++運(yùn)行庫(kù),如果你需要你的NDK程序中使用STL,則可以設(shè)置APP_STL := stlport_static,APP_STL有表二中的幾種取值。
NameExplanation
system(default)系統(tǒng)默認(rèn)的C++運(yùn)行庫(kù)
stlport_static以靜態(tài)鏈接方式使用的sttport版本的STL
stlport_shared以動(dòng)態(tài)鏈接方式使用的sttport版本的STL
gnustl_static以靜態(tài)鏈接方式使用的gnustl版本的STL
gnustl_shared以動(dòng)態(tài)鏈接方式使用的gnustl版本的STL
gabi++_static以靜態(tài)鏈接方式使用的gabi++
gabi++_shared以動(dòng)態(tài)鏈接方式使用的gabi++
c++_static以靜態(tài)鏈接方式使用的LLVM libc++
c++_shared以動(dòng)態(tài)鏈接方式使用的LLVM libc++
表二:NDK運(yùn)行庫(kù)
若APK中有多個(gè)SO文件用到STL,建議都使用動(dòng)態(tài)方式鏈接STL,這樣可以減小整個(gè)APK文件大小。
另外需要注意的是官方提供的NDK運(yùn)行庫(kù)除了默認(rèn)的以外都支持RTTI和異常,然而默認(rèn)是禁用的,將在下面的Android.mk中說明如何開啟。
APP_OPTIM(編譯模式)
“release”模式為默認(rèn)的,生成的是優(yōu)化后的二進(jìn)制;也可以設(shè)置為“debug”模式,“debug”模式生成的是未優(yōu)化二進(jìn)制,提供很多BUG信息,便于調(diào)試和分析
APP_PLATFORM
指定當(dāng)前程序支持android最低api水平,如APPP_PLATFORM:=16 最低支持到api16
編碼實(shí)戰(zhàn)
這里以我項(xiàng)目中使用ndk生成密匙一個(gè)例子進(jìn)行講解,實(shí)際項(xiàng)目中肯定會(huì)用到加密功能,有一些敏感的數(shù)據(jù)如用戶的密碼、賬號(hào)等,需要將這些信息保存到本地一旦數(shù)據(jù)保存到磁盤上,如果不進(jìn)行加密很有可能泄漏,造成不良的后果。
通過生成.so文件生成密匙,在一定程度上降低被盜風(fēng)險(xiǎn),畢竟這里邊設(shè)計(jì)到底層的東西比較多,安全性比硬編碼之類的高了好幾個(gè)檔次。
1、所有文件存放的位置截圖
2、Android.mk配置詳細(xì)信息
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=secretkey
LOCAL_SRC_FILES:=secretkey.cpp secretkey.h
LOCAL_LDLIBS :=-llog
include $(BUILD_SHARED_LIBRARY)
3、Application.mk配置詳細(xì)信息
APP_STL := stlport_static
APP_ABI := all
#app支持最小api level
APP_PLATFORM:= android-16
APP_OPTIM? := release
4、secretkey.h
#include
#defineUTF_8"UTF-8"
#ifdef__cplusplus
extern"C"{
//com.mine.cui.zxandroidlib.jni.com.mine.cui.zxandroidlib.security.SecretKeyHelper.createSecretKey
jstring
Java_com_test_lib_security_SecretKeyHelper_createSecretKey(JNIEnv*,jobject,jobject);
}
#endif
方法格式:jstring Java+全類名 (其中.用下劃線分隔開)+java定義native方法的類名和native方法名
5、secretkey.app
#include
#include
#include"secretkey.h"
#include
#include
#defineLOG_TAG"robin_jni"http:// 自定義的LOG的標(biāo)識(shí)
#defineLOGOPEN1//日志開關(guān),1為開,其它為關(guān)
#defineLOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#defineLOGI(...)? __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#defineLOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
#defineLOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
#defineLOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
//char* to jstring
jstringtoString(JNIEnv* env,jbyteArraybyteArray) {
jclassstring_cls = env->FindClass("java/lang/String");
jmethodIDnew_string_mid = env->GetMethodID(string_cls,"",
"([BLjava/lang/String;)V");
return reinterpret_cast(env->NewObject(string_cls, new_string_mid,
byteArray, env->NewStringUTF(UTF_8)));
}
jbyteArraytoBytes(JNIEnv* env,const char* bytes) {
jclassstring_cls = env->FindClass("java/lang/String");
jmethodIDget_bytes_mid = env->GetMethodID(string_cls,"getBytes",
"(Ljava/lang/String;)[B");
return reinterpret_cast(env->CallObjectMethod(
env->NewStringUTF(bytes), get_bytes_mid, env->NewStringUTF(UTF_8)));
}
jbyteArraytoBytes(JNIEnv* env,jstringstring) {
jclassstring_cls = env->FindClass("java/lang/String");
jmethodIDget_bytes_mid = env->GetMethodID(string_cls,"getBytes",
"(Ljava/lang/String;)[B");
return reinterpret_cast(env->CallObjectMethod(string,
get_bytes_mid, env->NewStringUTF(UTF_8)));
}
jbyteArraygetDigestedBytes(JNIEnv* env,jbyteArraycomplex_bytes) {
staticjobjectsatic_message_digest_obj = __null;
jclassmessage_digest_cls = env->FindClass("java/security/MessageDigest");
jmethodIDget_instance_mid = env->GetStaticMethodID(message_digest_cls,
"getInstance","(Ljava/lang/String;)Ljava/security/MessageDigest;");
if(satic_message_digest_obj == __null) {
jobjectlocal_message_digest_obj = env->CallStaticObjectMethod(
message_digest_cls, get_instance_mid, env->NewStringUTF("MD5"));
satic_message_digest_obj = env->NewGlobalRef(local_message_digest_obj);
env->DeleteLocalRef(local_message_digest_obj);
}
jmethodIDdigest_mid = env->GetMethodID(message_digest_cls,"digest",
"([B)[B");
env->DeleteLocalRef(message_digest_cls);
return reinterpret_cast(env->CallObjectMethod(
satic_message_digest_obj, digest_mid, complex_bytes));
}
jstringtoHex(JNIEnv* env,jbyteArraydigested_bytes) {
jclassbig_integer_cls = env->FindClass("java/math/BigInteger");
jmethodIDnew_big_integer_mid = env->GetMethodID(big_integer_cls,"",
"(I[B)V");
jobjectbig_integer_obj = env->NewObject(big_integer_cls,
new_big_integer_mid,1, digested_bytes);
env->DeleteLocalRef(digested_bytes);
jmethodIDto_String_mid = env->GetMethodID(big_integer_cls,"toString",
"(I)Ljava/lang/String;");
env->DeleteLocalRef(big_integer_cls);
return reinterpret_cast(env->CallObjectMethod(big_integer_obj,
to_String_mid,16));
}
jstringgetMD5(JNIEnv* env,jstringjInfo) {
jbyteArraydigested_bytes = getDigestedBytes(env, toBytes(env, jInfo));
returntoHex(env, digested_bytes);
}
jstringgetAppendedString(JNIEnv* env,jobjectthiz,jstrings1,jstrings2) {
const char*s1x = (env)->GetStringUTFChars(s1,NULL);
const char*s2x = (env)->GetStringUTFChars(s2,NULL);
char*sall =new char[strlen(s1x) + strlen(s2x) +1];
strcpy(sall, s1x);
strcat(sall, s2x);
jstringretval = (env)->NewStringUTF(sall);
(env)->ReleaseStringUTFChars(s1, s1x);
(env)->ReleaseStringUTFChars(s2, s2x);
free(sall);
returnretval;
}
jobjectgetInstance(JNIEnv* env,jclassobj_class) {
jmethodIDconstruction_id = env->GetMethodID(obj_class,"","()V");
jobjectobj = env->NewObject(obj_class, construction_id);
returnobj;
}
//獲取deviceid
jstringgetDeviceID(JNIEnv*env,jobjectthiz,jobjectmContext) {
jclasscls_context = (env)->FindClass("android/content/Context");
if(cls_context ==0) {
return(env)->NewStringUTF("unknown");
}
jmethodIDgetSystemService = (env)->GetMethodID(cls_context,
"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
if(getSystemService ==0) {
return(env)->NewStringUTF("unknown");
}
jfieldIDTELEPHONY_SERVICE = (env)->GetStaticFieldID(cls_context,
"TELEPHONY_SERVICE","Ljava/lang/String;");
if(TELEPHONY_SERVICE ==0) {
return(env)->NewStringUTF("unknown");
}
jobjectstr = (env)->GetStaticObjectField(cls_context, TELEPHONY_SERVICE);
jobjecttelephonymanager = (env)->CallObjectMethod(mContext,
getSystemService, str);
if(telephonymanager ==0) {
return(env)->NewStringUTF("unknown");
}
jclasscls_tm = (env)->FindClass("android/telephony/TelephonyManager");
if(cls_tm ==0) {
return(env)->NewStringUTF("unknown");
}
jmethodIDgetDeviceId = (env)->GetMethodID(cls_tm,"getDeviceId",
"()Ljava/lang/String;");
if(getDeviceId ==0) {
return(env)->NewStringUTF("unknown");
}
jobjectdeviceid = (env)->CallObjectMethod(telephonymanager, getDeviceId);
return(jstring) deviceid;
}
//獲取SerialNumber
jstringgetSerialNumber(JNIEnv*env,jobjectthiz,jobjectmContext) {
jclasscls_tm = (env)->FindClass("android/os/SystemProperties");
if(cls_tm ==0) {
return(env)->NewStringUTF("unknown");
}
jmethodIDgetDeviceId = (env)->GetStaticMethodID(cls_tm,"get",
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
if(getDeviceId ==0) {
return(env)->NewStringUTF("unknown");
}
jstringparam1 = (env)->NewStringUTF("ro.serialno");
jstringparam2 = (env)->NewStringUTF("unknown");
jobjectdeviceid = (env)->CallStaticObjectMethod(cls_tm, getDeviceId,
param1, param2);
return(jstring) deviceid;
}
jstringjint2jstring(JNIEnv*env,jintfirst) {
charbuf[64];// assumed large enough to cope with result
sprintf(buf,"%d", first);// error checking omitted
returnenv->NewStringUTF( buf);
}
//獲取公鑰
jstringgetPublicKey(JNIEnv* env,jobjectthiz,jobjectcontext) {
jclasscontext_cls = env->GetObjectClass(context);
jmethodIDget_package_manager_mid = env->GetMethodID(context_cls,
"getPackageManager","()Landroid/content/pm/PackageManager;");
jmethodIDget_package_name_mid = env->GetMethodID(context_cls,
"getPackageName","()Ljava/lang/String;");
env->DeleteLocalRef(context_cls);
jobjectpm_obj = env->CallObjectMethod(context, get_package_manager_mid);
jclasspm_cls = env->FindClass("android/content/pm/PackageManager");
jmethodIDget_package_info_mid = env->GetMethodID(pm_cls,"getPackageInfo",
"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jstringpackage_name =reinterpret_cast(env->CallObjectMethod(
context, get_package_name_mid));
jfieldIDflag_fid = env->GetStaticFieldID(pm_cls,"GET_SIGNATURES","I");
jintflag = env->GetStaticIntField(pm_cls, flag_fid);
env->DeleteLocalRef(pm_cls);
jobjectpi_obj = env->CallObjectMethod(pm_obj, get_package_info_mid,
package_name, flag);
env->DeleteLocalRef(package_name);
jclasspi_cls = env->FindClass("android/content/pm/PackageInfo");
jfieldIDsignatures_fid = env->GetFieldID(pi_cls,"signatures",
"[Landroid/content/pm/Signature;");
env->DeleteLocalRef(pi_cls);
jobjectsig_obj = env->GetObjectField(pi_obj, signatures_fid);
env->DeleteLocalRef(pi_obj);
jobjectArraysigs =reinterpret_cast(sig_obj);
jclasssignature_cls = env->FindClass("android/content/pm/Signature");
jmethodIDto_byte_array_mid = env->GetMethodID(signature_cls,"toByteArray",
"()[B");
jbyteArraysig_bytes =reinterpret_cast(env->CallObjectMethod(
env->GetObjectArrayElement(sigs,0), to_byte_array_mid));
jclasscertificate_factory_cls = env->FindClass(
"java/security/cert/CertificateFactory");
jmethodIDget_certificate_instance_mid = env->GetStaticMethodID(
certificate_factory_cls,"getInstance",
"(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;");
jobjectcertificate_factory_obj = env->CallStaticObjectMethod(
certificate_factory_cls, get_certificate_instance_mid,
env->NewStringUTF("X509"));
jmethodIDgenerate_certificate_mid = env->GetMethodID(
certificate_factory_cls,"generateCertificate",
"(Ljava/io/InputStream;)Ljava/security/cert/Certificate;");
env->DeleteLocalRef(certificate_factory_cls);
jclasscertificate_cls = env->FindClass("java/security/cert/Certificate");
jclassbyte_input_stream_cls = env->FindClass(
"java/io/ByteArrayInputStream");
jmethodIDnew_sig_bytes_is_mid = env->GetMethodID(byte_input_stream_cls,
"","([B)V");
jobjectsig_bytes_is = env->NewObject(byte_input_stream_cls,
new_sig_bytes_is_mid, sig_bytes);
env->DeleteLocalRef(sig_bytes);
env->DeleteLocalRef(byte_input_stream_cls);
jobjectcert = env->CallObjectMethod(certificate_factory_obj,
generate_certificate_mid, sig_bytes_is);
env->DeleteLocalRef(sig_bytes_is);
env->DeleteLocalRef(certificate_factory_obj);
jmethodIDget_pubic_key_mid = env->GetMethodID(certificate_cls,
"getPublicKey","()Ljava/security/PublicKey;");
env->DeleteLocalRef(certificate_cls);
jobjectpublicKey? = env->CallObjectMethod(cert, get_pubic_key_mid);
jclasspublicKey_cls = env->GetObjectClass(publicKey);
jmethodIDtoString_mid = env->GetMethodID(publicKey_cls,"toString","()Ljava/lang/String;");
jstringpublicKey_str =static_cast(env->CallObjectMethod(publicKey,toString_mid));
env->DeleteLocalRef(cert);
env->DeleteLocalRef(publicKey_cls);
env->DeleteLocalRef(publicKey);
jclassstring_cls = env->GetObjectClass(publicKey_str);
jmethodIDindexOf_mid = env->GetMethodID(string_cls,"indexOf","(Ljava/lang/String;)I");
jstringparam = env->NewStringUTF("modulus");
jintaa = env->CallIntMethod(publicKey_str,indexOf_mid,param);
jstringparam2 = env->NewStringUTF("publicExponent");
jintbb = env->CallIntMethod(publicKey_str,indexOf_mid,param2);
jmethodIDsubstring_mid = env->GetMethodID(string_cls,"substring","(II)Ljava/lang/String;");
jstringpublicKey2_str =static_cast(env->CallObjectMethod(publicKey_str,substring_mid,aa+8,bb-1));
returnpublicKey2_str;
}
//獲取簽名
jstringgetSignatures(JNIEnv* env,jobjectthizz,
jobjectthiz) {
jclassnative_clazz = env->GetObjectClass(thiz);
// 得到 getPackageManager 方法的 ID
jmethodIDmethodID_func = env->GetMethodID(native_clazz,
"getPackageManager","()Landroid/content/pm/PackageManager;");
// 獲得應(yīng)用包的管理器
jobjectpackage_manager = env->CallObjectMethod(thiz, methodID_func);
// 獲得 PackageManager 類
jclasspm_clazz = env->GetObjectClass(package_manager);
// 得到 getPackageInfo 方法的 ID
jmethodIDmethodID_pm = env->GetMethodID(pm_clazz,"getPackageInfo",
"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
//獲取包名
jmethodIDmethodID_packagename = env->GetMethodID(native_clazz,
"getPackageName","()Ljava/lang/String;");
jstringname_str =static_cast(env->CallObjectMethod(thiz,
methodID_packagename));
// 獲得應(yīng)用包的信息
jobjectpackage_info = env->CallObjectMethod(package_manager, methodID_pm,
name_str,64);//env->NewStringUTF("com.example.contasdf")
// 獲得 PackageInfo 類
jclasspi_clazz = env->GetObjectClass(package_info);
// 獲得簽名數(shù)組屬性的 ID
jfieldIDfieldID_signatures = env->GetFieldID(pi_clazz,"signatures",
"[Landroid/content/pm/Signature;");
// 得到簽名數(shù)組,待修改
jobjectsignatur = env->GetObjectField(package_info, fieldID_signatures);
jobjectArraysignatures =reinterpret_cast(signatur);
// 得到簽名
jobjectsignature = env->GetObjectArrayElement(signatures,0);
// 獲得 Signature 類,待修改
jclasss_clazz = env->GetObjectClass(signature);
// 得到 hashCode 方法的 ID
jmethodIDmethodID_hc = env->GetMethodID(s_clazz,"hashCode","()I");
// 獲得應(yīng)用包的管理器,待修改
inthash_code = env->CallIntMethod(signature, methodID_hc);
charstr[100];
sprintf(str,"%u", hash_code);
jstringsign = env->NewStringUTF(str);
returnsign;
}
jstringgetPackageName(JNIEnv* env,jobjectthizz,jobjectthiz) {
jclassnative_clazz = env->GetObjectClass(thiz);
// 得到 getPackageManager 方法的 ID
jmethodIDmethodID_func = env->GetMethodID(native_clazz,
"getPackageManager","()Landroid/content/pm/PackageManager;");
// 獲得應(yīng)用包的管理器
jobjectpackage_manager = env->CallObjectMethod(thiz, methodID_func);
// 獲得 PackageManager 類
jclasspm_clazz = env->GetObjectClass(package_manager);
// 得到 getPackageInfo 方法的 ID
jmethodIDmethodID_pm = env->GetMethodID(pm_clazz,"getPackageInfo",
"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
//獲取包名
jmethodIDmethodID_packagename = env->GetMethodID(native_clazz,
"getPackageName","()Ljava/lang/String;");
jstringname_str =static_cast(env->CallObjectMethod(thiz,
methodID_packagename));
returnname_str;
}
char* jstringTostring(JNIEnv* env,jstringjstr)
{
char* rtn =NULL;
jclassclsstring = env->FindClass("java/lang/String");
jstringstrencode = env->NewStringUTF("utf-8");
jmethodIDmid = env->GetMethodID(clsstring,"getBytes","(Ljava/lang/String;)[B");
jbyteArraybarr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsizealen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr,JNI_FALSE);
if(alen >0)
{
rtn = (char*)malloc((size_t) (alen +1));
memcpy(rtn, ba, (size_t) alen);
rtn[alen] =0;
}
env->ReleaseByteArrayElements(barr, ba,0);
returnrtn;
}
jstring Java_com_test_lib_security_SecretKeyHelper_createSecretKey(JNIEnv* env,jobjectthizz,
jobjectthiz) {
jstringimei = getAppendedString(env, thizz, getDeviceID(env, thizz, thiz),getSerialNumber(env, thizz, thiz));
if(LOGOPEN==1){
LOGD("imei = %s",jstringTostring(env,imei));
}
jstringsign = getPublicKey(env, thizz, thiz);
if(LOGOPEN==1){
LOGD("sign = %s",jstringTostring(env,sign));
}
jstringimei_sign = getAppendedString(env, thizz, imei, sign);
if(LOGOPEN==1){
LOGD("imei_sign = %s",jstringTostring(env,imei_sign));
}
jstringpackage = getPackageName(env, thizz, thiz);
if(LOGOPEN==1){
LOGD("package = %s",jstringTostring(env,package));
}
jstringimei_sign_package = getAppendedString(env, thizz, imei_sign,package);
if(LOGOPEN==1){
LOGD("imei_sign_package = %s",jstringTostring(env,imei_sign_package));
}
//請(qǐng)?jiān)偌尤胱约旱囊莆换蛱鎿Q 或其他加密算法,例如我又append了一次imei
imei_sign_package = getAppendedString(env, thizz, imei_sign_package, imei);
if(LOGOPEN==1){
LOGD("imei_sign_package2 = %s",jstringTostring(env,imei_sign_package));
}
imei_sign_package = getAppendedString(env, thizz, imei_sign_package, sign);
if(LOGOPEN==1){
LOGD("imei_sign_package3 = %s",jstringTostring(env,imei_sign_package));
}
jstringsecretKey = getMD5(env, imei_sign_package);
if(LOGOPEN==1){
LOGD("secretKey = %s",jstringTostring(env,secretKey));
}
returnsecretKey;
}
6、、
public class SecretKeyHelper {
static{
System.loadLibrary("secretkey");
}
private staticStringmKey;
public staticString getSecretKey(Context context) {
if(mKey==null) {
mKey=createSecretKey(context);
}
returnmKey;
}
public static nativeString createSecretKey(Context context);
}
8、