標籤:
博文轉自http://www.tuicool.com/articles/UVjme2r,感謝博主的分享
為了防止被反編譯,打算把關鍵代碼寫到so裡(比如加解密),在so裡加上判斷APk包簽名是否一致的代碼,避免so被二次打包。其實用JNI讀簽名就是用了Java的反射機制。
先看Java讀取簽名的方法:
1 try {2 PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 64);3 Signature sign = info.signatures[0];4 Log.i("test", "hashCode : " + sign.hashCode());5 } catch (NameNotFoundException e) {6 e.printStackTrace();7 }View Code
然後我們用JNI c語言實現,同樣需要傳遞Context:
1 int getSignHashCode(JNIEnv *env, jobject context) { 2 //Context的類 3 jclass context_clazz = (*env)->GetObjectClass(env, context); 4 // 得到 getPackageManager 方法的 ID 5 jmethodID methodID_getPackageManager = (*env)->GetMethodID(env, context_clazz, 6 "getPackageManager", "()Landroid/content/pm/PackageManager;"); 7 8 // 獲得PackageManager對象 9 jobject packageManager = (*env)->CallObjectMethod(env, context,10 methodID_getPackageManager);11 // // 獲得 PackageManager 類12 jclass pm_clazz = (*env)->GetObjectClass(env, packageManager);13 // 得到 getPackageInfo 方法的 ID14 jmethodID methodID_pm = (*env)->GetMethodID(env, pm_clazz, "getPackageInfo",15 "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");16 //17 // // 得到 getPackageName 方法的 ID18 jmethodID methodID_pack = (*env)->GetMethodID(env, context_clazz,19 "getPackageName", "()Ljava/lang/String;");20 21 // 獲得當前應用的包名22 jstring application_package = (*env)->CallObjectMethod(env, context,23 methodID_pack);24 const char *str = (*env)->GetStringUTFChars(env, application_package, 0);25 __android_log_print(ANDROID_LOG_DEBUG, "JNI", "packageName: %s\n", str);26 27 // 獲得PackageInfo28 jobject packageInfo = (*env)->CallObjectMethod(env, packageManager,29 methodID_pm, application_package, 64);30 31 jclass packageinfo_clazz = (*env)->GetObjectClass(env, packageInfo);32 jfieldID fieldID_signatures = (*env)->GetFieldID(env, packageinfo_clazz,33 "signatures", "[Landroid/content/pm/Signature;");34 jobjectArray signature_arr = (jobjectArray)(*env)->GetObjectField(env,35 packageInfo, fieldID_signatures);36 //Signature數組中取出第一個元素37 jobject signature = (*env)->GetObjectArrayElement(env, signature_arr, 0);38 //讀signature的hashcode39 jclass signature_clazz = (*env)->GetObjectClass(env, signature);40 jmethodID methodID_hashcode = (*env)->GetMethodID(env, signature_clazz,41 "hashCode", "()I");42 jint hashCode = (*env)->CallIntMethod(env, signature, methodID_hashcode);43 __android_log_print(ANDROID_LOG_DEBUG, "JNI", "hashcode: %d\n", hashCode);44 return hashCode;45 }View Code
第二個參數jobject不是JNI函數的預設參數,而是傳入的Context執行個體。
轉:Android開發:使用JNI讀取應用簽名