ndk的环境配置就不写了,网上很多
首先新建一个项目,然后在包名下新建一个类,定义自己需要的native方法
public class SingatureClass {
//验证包名
public native String verificationPackage(Object context);
//验证签名
public native String verificationSign(Object context);
}
其次要获取到项目的签名值
这里需要注意的地方是debug包和release包的签名是不一样的,如果要获取release包的签名值,则需要把该方法生成的签名值先写入本地日志, 然后从日志中获取签名值,将获取到的签名值复制到.c文件中
public static String getSignature(Context context) {
try {
/** 通过包管理器获得指定包名包含签名的包信息 **/
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
/******* 通过返回的包信息获得签名数组 *******/
Signature[] signatures = packageInfo.signatures;
/******* 循环遍历签名数组拼接应用签名 *******/
return signatures[0].toCharsString();
/************** 得到应用签名 **************/
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
接下来生成.h文件
打开Terminal,
输入cd app/src/main/java,键入Enter
然后输入javah -d ../jni -classpath . -jni 包名.类名
如果出现错误:“错误: 编码GBK的不可映射字符”,
则输入javah -d ../jni -classpath . -jni -encoding UTF-8 包名.类名
在main目录下新建jni文件夹,将生成的.h文件移动到jni目录下
然后在jni目录先新建c/c++文件
将.h中的生成的方法复制到新建的c文件中,并且添加引用
将签名值和包名进行赋值
下面贴出代码
#include "com_lee_signatureencryption_SingatureClass.h"
#include <jni.h>
#include <string.h>
#include <unistd.h>
/**
* 发布的app 签名,只有和本签名一致的app 才会返回 AUTH_KEY
* 这个RELEASE_SIGN的值是上一步用java代码获取的值
*/
const char* RELEASE_SIGN = "********92a864886f70d010";
const char* RELEASE_PACKAGE = "com.lee.signatureencryption";
JNIEXPORT jstring JNICALL Java_com_lee_signatureencryption_SingatureClass_verificationPackage
(JNIEnv *env, jobject jobj, jobject context_object){
jclass context_class = env->GetObjectClass(context_object);
//context.getPackageManager()
jmethodID methodId = env->GetMethodID(context_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject package_manager_object = env->CallObjectMethod(context_object, methodId);
if (package_manager_object == NULL) {
return NULL;
}
//context.getPackageName()
methodId = env->GetMethodID(context_class, "getPackageName", "()Ljava/lang/String;");
jstring package_name_string = (jstring)env->CallObjectMethod(context_object, methodId);
if (package_name_string == NULL) {
return NULL;
}
const char* c_package = (char*)env->GetStringUTFChars(package_name_string, 0);
if(strcmp(c_package, RELEASE_PACKAGE) == 0) {
return (env)->NewStringUTF("package true");
} else {
return (env)->NewStringUTF("package error");
}
}
JNIEXPORT jstring JNICALL Java_com_lee_signatureencryption_SingatureClass_verificationSign
(JNIEnv *env, jobject jobj, jobject context_object){
jclass context_class = env->GetObjectClass(context_object);
//context.getPackageManager()
jmethodID methodId = env->GetMethodID(context_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject package_manager_object = env->CallObjectMethod(context_object, methodId);
if (package_manager_object == NULL) {
return NULL;
}
//context.getPackageName()
methodId = env->GetMethodID(context_class, "getPackageName", "()Ljava/lang/String;");
jstring package_name_string = (jstring)env->CallObjectMethod(context_object, methodId);
if (package_name_string == NULL) {
return NULL;
}
env->DeleteLocalRef(context_class);
//PackageManager.getPackageInfo(Sting, int)
jclass pack_manager_class = env->GetObjectClass(package_manager_object);
methodId = env->GetMethodID(pack_manager_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
env->DeleteLocalRef(pack_manager_class);
jobject package_info_object = env->CallObjectMethod(package_manager_object, methodId, package_name_string, 64);
if (package_info_object == NULL) {
return NULL;
}
env->DeleteLocalRef(package_manager_object);
//PackageInfo.signatures[0]
jclass package_info_class = env->GetObjectClass(package_info_object);
jfieldID fieldId = env->GetFieldID(package_info_class, "signatures", "[Landroid/content/pm/Signature;");
env->DeleteLocalRef(package_info_class);
jobjectArray signature_object_array = (jobjectArray)env->GetObjectField(package_info_object, fieldId);
if (signature_object_array == NULL) {
return NULL;
}
jobject signature_object = env->GetObjectArrayElement(signature_object_array, 0);
env->DeleteLocalRef(package_info_object);
//Signature.toCharsString()
jclass signature_class = env->GetObjectClass(signature_object);
methodId = env->GetMethodID(signature_class, "toCharsString", "()Ljava/lang/String;");
env->DeleteLocalRef(signature_class);
jstring signature_string = (jstring) env->CallObjectMethod(signature_object, methodId);
const char* c_sign = (char*)env->GetStringUTFChars(signature_string, 0);
//签名一致 返回合法的 api key,否则返回错误
if(strcmp(c_sign, RELEASE_SIGN)==0) {
return (env)->NewStringUTF("sign true");
} else {
return (env)->NewStringUTF("sign error");
}
}
然后在jni 中添加Android.mk、Application.mk两个文件
Android.mk
MY_LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := signature
LOCAL_SRC_FILES := signature.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
APP_PLATFORM := android-14
在app 下的build.gradle中添加配置
android{
......
sourceSets {
main {
jni.srcDirs = []
}
}
repositories {
flatDir {
dirs 'libs'
}
}
}
打开Terminal
输入 cd app/src/main/jni Enter
输入 ndk-build
等待几分钟时间,编译成功后,将会生成libs和obj文件夹
libs中的文件就是我们需要的so
在main目录下新建jniLibs文件夹,然后将libs中的文件全部拷贝到jniLibs中