jni中调用java方法获取当前apk的签名文件md5值

相应的java方法:

void getsign(Context context) throws Exception {
    PackageInfo localPackageInfo = context.getPackageManager()
            .getPackageInfo(context.getPackageName(), 64);
    StringBuilder localStringBuilder = new StringBuilder();
    Signature[] arrayOfSignature = localPackageInfo.signatures;
    Signature localSignature = arrayOfSignature[0];

    MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
    localMessageDigest.update(localSignature.toByteArray());
    // 这个就是签名的md5值
    String str2 = toHex(localMessageDigest.digest());
}

private String toHex(byte[] paramArrayOfByte) {
    StringBuffer localStringBuffer = new StringBuffer();
    for (int i = 0; i < paramArrayOfByte.length; i++) {
        Object[] arrayOfObject = new Object[1];
        arrayOfObject[0] = Byte.valueOf(paramArrayOfByte[i]);
        localStringBuffer.append(String.format("%02x", arrayOfObject));
    }
    return localStringBuffer.toString();
}

jni中可以调用java的方法,参照上面的java方法可以对应写出jni的c代码:

// 字节流转换为十六进制字符串
//http://blog.csdn.net/pingd/article/details/41945417
void ByteToHexStr(const unsigned char* source, char* dest, int sourceLen)
{
    short i;
    unsigned char highByte, lowByte;

    for (i = 0; i < sourceLen; i++)
    {
        highByte = source[i] >> 4;
        lowByte = source[i] & 0x0f;

        highByte += 0x30;

        if (highByte > 0x39)
                dest[i * 2] = highByte + 0x07;
        else
                dest[i * 2] = highByte;

        lowByte += 0x30;
        if (lowByte > 0x39)
            dest[i * 2 + 1] = lowByte + 0x07;
        else
            dest[i * 2 + 1] = lowByte;
    }
    return;
}

JNIEXPORT jstring JNICALL Java_com_hengbao_util_DecodeUtil_test(JNIEnv * env, jobject thiz, jobject context) {
    //java code=======================================================
    //      PackageInfo localPackageInfo = context.getPackageManager()
    //              .getPackageInfo(context.getPackageName(), 64);
    //      StringBuilder localStringBuilder = new StringBuilder();
    //      Signature[] arrayOfSignature = localPackageInfo.signatures;
    //      Signature localSignature = arrayOfSignature[0];
    //      MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
    //      localMessageDigest.update(localSignature.toByteArray());
    //      // 这个就是签名的md5值
    //      String str2 = toHex(localMessageDigest.digest());
    //      localStringBuilder.append("Signature of ")
    //              .append(localPackageInfo.packageName).append(‘\n‘).append(str2);
    //      System.out.println(localStringBuilder.toString());
    //      TextView tv = (TextView) findViewById(R.id.tv);
    //      tv.setText(localStringBuilder.toString());

    //  private String toHex(byte[] paramArrayOfByte) {
    //      StringBuffer localStringBuffer = new StringBuffer();
    //      for (int i = 0; i < paramArrayOfByte.length; i++) {
    //          Object[] arrayOfObject = new Object[1];
    //          arrayOfObject[0] = Byte.valueOf(paramArrayOfByte[i]);
    //          localStringBuffer.append(String.format("%02x", arrayOfObject));
    //      }
    //      return localStringBuffer.toString();
    //  }
    //java code======================================================

    jclass tem_class;
    jmethodID tem_method;
    jclass class_context = (*env)->GetObjectClass(env, context);
    //      PackageInfo localPackageInfo = context.getPackageManager()
    //              .getPackageInfo(context.getPackageName(), 64);
    tem_method = (*env)->GetMethodID(env, class_context, "getPackageManager", "()Landroid/content/pm/PackageManager;");
    jobject obj_package_manager = (*env)->CallObjectMethod(env, context, tem_method);
    // getPackageName
    tem_method = (*env)->GetMethodID(env, class_context, "getPackageName", "()Ljava/lang/String;");
    jobject obj_package_name = (*env)->CallObjectMethod(env, context, tem_method);
    // getPackageInfo
    tem_class = (*env)->GetObjectClass(env, obj_package_manager);
    tem_method = (*env)->GetMethodID(env, tem_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jobject obj_package_info = (*env)->CallObjectMethod(env, obj_package_manager, tem_method, obj_package_name, 64);

    // Signature[] arrayOfSignature = localPackageInfo.signatures;
    // Signature localSignature = arrayOfSignature[0];
    tem_class = (*env)->GetObjectClass(env, obj_package_info);
    jfieldID fieldID_signatures = (*env)->GetFieldID(env, tem_class, "signatures", "[Landroid/content/pm/Signature;");
    jobjectArray signatures = (*env)->GetObjectField(env, obj_package_info, fieldID_signatures);
    jobject signature = (*env)->GetObjectArrayElement(env, signatures, 0);
    // localSignature.toByteArray()
    tem_class = (*env)->GetObjectClass(env, signature);
    tem_method = (*env)->GetMethodID(env, tem_class, "toByteArray", "()[B");
    jobject obj_sign_byte_array = (*env)->CallObjectMethod(env, signature, tem_method);// 这个就是拿到的签名byte数组

    //      MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
    jclass class_MessageDigest = (*env)->FindClass(env, "java/security/MessageDigest");
    tem_method = (*env)->GetStaticMethodID(env, class_MessageDigest, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
    jobject obj_md5 = (*env)->CallStaticObjectMethod(env, class_MessageDigest, tem_method, (*env)->NewStringUTF(env, "md5"));
    //      localMessageDigest.update(localSignature.toByteArray());
    //tem_class = (*env)->GetObjectClass(env, obj_md5);
    tem_method = (*env)->GetMethodID(env, class_MessageDigest, "update", "([B)V");// 这个函数的返回值是void,写V
    (*env)->CallVoidMethod(env, obj_md5, tem_method, obj_sign_byte_array);
    // localMessageDigest.digest()
    tem_method = (*env)->GetMethodID(env, class_MessageDigest, "digest", "()[B");
    // 这个是md5以后的byte数组,现在只要将它转换成16进制字符串,就可以和之前的比较了
    jobject obj_array_sign = (*env)->CallObjectMethod(env, obj_md5, tem_method);// jni中有强转类型的概念吗
    //      // 这个就是签名的md5值
    //      String str2 = toHex(localMessageDigest.digest());

    // 尝试用c写一下:http://blog.csdn.net/pingd/article/details/41945417
    jsize int_array_length = (*env)->GetArrayLength(env, obj_array_sign);
    jbyte* byte_array_elements = (*env)->GetByteArrayElements(env, obj_array_sign, JNI_FALSE);
    char* char_result = (char*) malloc(int_array_length*2+1);// 开始没有+1,在有的情况下会越界产生问题,还是在后面补上\0比较好
    // 将byte数组转换成16进制字符串,发现这里不用强转,jbyte和unsigned char应该字节数是一样的
    ByteToHexStr(byte_array_elements, char_result, int_array_length);
    *(char_result+int_array_length*2) = ‘\0‘;// 在末尾补\0
    jstring string_result = (*env)->NewStringUTF(env, char_result);
    // release
    (*env)->ReleaseByteArrayElements(env, obj_array_sign, byte_array_elements, JNI_ABORT);
    // 释放指针使用free
    free(char_result);
    return string_result;

    // 如果使用java的16进制转换的话,应该也可以的,用c写16进制转换太麻烦
    //jclass class_HandleData = (*env)->FindClass(env, "com/hengbao/util/HandleData");
    //tem_method = (*env)->GetStaticMethodID(env, class_HandleData, "bytesToHexString1", "([B)Ljava/lang/String;");
    //jobject obj_result = (*env)->CallStaticObjectMethod(env, class_HandleData, tem_method, obj_array_sign);
    //return obj_result;
}
时间: 2024-12-14 18:12:08

jni中调用java方法获取当前apk的签名文件md5值的相关文章

cocos2d-x中使用JNI的调用JAVA方法

用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化语言(如C\C++)与JAVA语言进行交互.在交互过程成中,JAVA调用的是已编译好的本地化语言的二进制代码(如Windows下的dll.Linux下的so文件).所以在交叉编译时看到Eclipse的控制台输出 [armeabi] SharedLibrary  : libcocos2dcpp.so

cocos2d 中使用jni C++ 调用 Java 方法

1.简单数据类型例子 假设我们Java中有这么一个open的静态方法,它没有参数,有一个int的返回值.怎么在C++中调用它呢? package cb.CbCCBLE; public class CbCCBLECentralManager { public static final String TAG = "CbCCBLECentralManager Android"; public static int open() { Log.d(TAG,"open"); r

Android JNI之调用JAVA方法的返回值签名

从http://blog.csdn.net/lonelyroamer/article/details/7932787截取的 如何签名: 下面看看Sign签名如何写,来表示要取得的属性或方法的类型. 1.普通类型签名 2.引用类型签名 object     L开头,然后以/ 分隔包的完整类型,后面再加:   比如说String    签名就是   Ljava/lang/String; Array      以[ 开头,在加上数组元素类型的签名            比如int[]   签名就是[I

Android Studio NDK开发-JNI调用Java方法

相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需要先了解FindClass和GetMethodID了. FindClass和GetMethodID 在JNI中可以通过FindClass可以找到Java类,得到jclass,例如: jclass clz=(*env)->FindClass(env,"com/jjz/JniHandle"

java native interface JNI 调用Java方法

在上一篇文章中介绍了JNI,以及java调用JNI,这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数.JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数. 下表列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数.每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对

如何在C/C++中调用Java

java跨平台的特性使Java越来越受开发人员的欢迎,但也往往会听到不少的抱怨:用Java开发的图形用户窗口界面每次在启动的时候都会跳出一个控制台窗口,这个控制台窗口让本来非常棒的界面失色不少.怎么能够让通过Java开发的GUI程序不弹出Java的控制台窗口呢?其实现在很多流行的开发环境例如JBuilder.Eclipse都是使用纯Java开发的集成环境.这些集成环境启动的时候并不会打开一个命令窗口,因为它使用了JNI(Java Native Interface)的技术.通过这种技术,开发人员不

Python调用java方法

需求 最近在后台项目代码中一段自定义的AES加解密的程序在平时的测试工作中应用频繁.因为写脚本经常会需要使用,而经过各种尝试,比如jpype等,都不尽如人意.最后转换思路找到了一种好方法: 1. 将java项目打成jar包: 2. 设定jar包的Main-class属性: 3. 在python中通过subprocess执行jar包. 修改main函数打jar包 在intellij中打jar包: 1. File--> Project Structure... --> Artifacts --&g

C通过JNI反向调用JAVA程序方法

JNI反向调用JAVA程序 引述:上文讲过java线程---OS线程的关系,然后C怎样反向调用JAVA程序方法是我们这篇讲的重点 1.ThreadTest中添加run()方法 2.编译ThreadTest.java         javac ThreadTest.java    生成ThreadTest.class 3.javah ThreadTest    生成 ThreadTest.h文件 4.编写ThreadNew.c文件 #include<pthread.h>#include<

入门: 使用JNI 从C++代码中调用Java的静态方法

开发环境: 操作系统: (uname -a output)  Linux ubuntu 3.8.0-19-generic #29-Ubuntu SMP Wed Apr 17 18:16:28 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux JDK 版本 : (java -version) java version "1.7.0_51"OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubun