Android开发:使用JNI读取应用签名

为了防止被反编译,打算把关键代码写到so里(比如加解密),在so里加上判断APk包签名是否一致的代码,避免so被二次打包。其实用JNI读签名就是用了Java的反射机制。
先看Java读取签名的方法:

		try {
			PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 64);
			Signature sign = info.signatures[0];
			Log.i("test", "hashCode : " + sign.hashCode());
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}

然后我们用JNI c语言实现,同样需要传递Context:

int getSignHashCode(JNIEnv *env, jobject context) {
	//Context的类
	jclass context_clazz = (*env)->GetObjectClass(env, context);
	// 得到 getPackageManager 方法的 ID
	jmethodID methodID_getPackageManager = (*env)->GetMethodID(env, context_clazz,
			"getPackageManager", "()Landroid/content/pm/PackageManager;");

	// 获得PackageManager对象
	jobject packageManager = (*env)->CallObjectMethod(env, context,
			methodID_getPackageManager);
//	// 获得 PackageManager 类
	jclass pm_clazz = (*env)->GetObjectClass(env, packageManager);
	// 得到 getPackageInfo 方法的 ID
	jmethodID methodID_pm = (*env)->GetMethodID(env, pm_clazz, "getPackageInfo",
			"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
//
//	// 得到 getPackageName 方法的 ID
	jmethodID methodID_pack = (*env)->GetMethodID(env, context_clazz,
			"getPackageName", "()Ljava/lang/String;");

	// 获得当前应用的包名
	jstring application_package = (*env)->CallObjectMethod(env, context,
			methodID_pack);
	const char *str = (*env)->GetStringUTFChars(env, application_package, 0);
	__android_log_print(ANDROID_LOG_DEBUG, "JNI", "packageName: %s\n", str);

	// 获得PackageInfo
	jobject packageInfo = (*env)->CallObjectMethod(env, packageManager,
			methodID_pm, application_package, 64);

	jclass packageinfo_clazz = (*env)->GetObjectClass(env, packageInfo);
	jfieldID fieldID_signatures = (*env)->GetFieldID(env, packageinfo_clazz,
			"signatures", "[Landroid/content/pm/Signature;");
	jobjectArray signature_arr = (jobjectArray)(*env)->GetObjectField(env,
			packageInfo, fieldID_signatures);
	//Signature数组中取出第一个元素
	jobject signature = (*env)->GetObjectArrayElement(env, signature_arr, 0);
	//读signature的hashcode
	jclass signature_clazz = (*env)->GetObjectClass(env, signature);
	jmethodID methodID_hashcode = (*env)->GetMethodID(env, signature_clazz,
			"hashCode", "()I");
	jint hashCode = (*env)->CallIntMethod(env, signature, methodID_hashcode);
	__android_log_print(ANDROID_LOG_DEBUG, "JNI", "hashcode: %d\n", hashCode);
	return hashCode;
}

第二个参数jobject不是JNI函数的默认参数,而是传入的Context实例。

© 2014, 冰冻鱼. 请尊重作者劳动成果,复制转载保留本站链接! 应用开发笔记

发表评论

电子邮件地址不会被公开。 必填项已用*标注