**android Studio 基于NDK加密，防止反编译获取加密key**

一、配置ndk路径（不会请自行百度）

1. 依次点击 File – Settings – Appearance&Behavior – System Settings – Android SDK – SDK Tools ，安装 NDK(版本不能太高，太高不能用,我用的是21.0.06.1113669版本) 和CMAke工具
2. 在项目中local.properties添加ndk路径，例如：ndk.dir=/Users/edy/Documents/Androidtools/android-sdk-macosx/ndk/21.0.6011959 
3. 环境变量里添加ndk路径，例如：export NDK_HOME=/Users/edy/Documents/Androidtools/android-sdk-macosx/ndk/21.0.6011959
export PATH=$PATH:$NDK_HOME 

二、新建SobotUtil类实现native方法
1. SobotUtil代码


public class SobotUtil {
    static {
        System.loadLibrary("sobot");
    }

    public static native String getSign(String a, String b, String c, String d, String e);

}



2. Build->先clean project，然后再rebuild project 生成class文件，生成的文件和SobotUtil.java挨着


3. - 打开命令行输入指令找到上一步的SobotUtil.java目录
- 在输入指令  javac -h . SobotUtil.java  即SobotUtil的路径，生成.h文件,例如：com_sobot_chat_utils_SobotUtil.h


4. 在src/main路径下新建一个名为jni的文件夹，将
com_sobot_chat_utils_SobotUtil.h

的.h文件拷贝到jni文件夹内，并在jni文件夹内新建一个以.c为后缀的类：sobot.c,名字随意，记住是.c不是.cpp，此类用来写实现的方法


5. 在.c里面写入执行加密代码的方法，代码不过多解释，如果有不懂的地方，可以参考：

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <com_sobot_chat_utils_SobotUtil.h>
#include <md5.h>

const char *KEY = "sobot*&^%$#@!";

char *jstringToChar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env, "utf-8");
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) (*env)->CallObjectMethod(env, jstr, mid, strencode);
    jsize alen = (*env)->GetArrayLength(env, barr);
    jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);
    return rtn;
}

JNIEXPORT jstring JNICALL Java_com_sobot_chat_utils_SobotUtil_getSign
  (JNIEnv *env, jclass j, jstring a, jstring b, jstring c, jstring d, jstring e){
    char *aa =jstringToChar(env,a);
    char *cc =jstringToChar(env,c);
    char *dd =jstringToChar(env,d);
    char *result = (char *) malloc(strlen(aa) + strlen(dd)+ strlen(cc)+ strlen(KEY));
    sprintf(result, "%s%s%s%s", aa,dd,cc,KEY);
    MD5_CTX context = { 0 };
    MD5Init(&context);
    MD5Update(&context, result, strlen(result));
    unsigned char dest[16] = { 0 };
    MD5Final(dest, &context);
    (*env)->ReleaseStringUTFChars(env, c, result);

    int i = 0;
    char szMd5[33] = { 0 };
    for (i = 0; i < 16; i++)
     {
          sprintf(szMd5, "%s%02x", szMd5, dest[i]);
     }
     return (*env)->NewStringUTF(env, szMd5);
}

6.jni下创建对应的文件，可参考sdk jni
Android.mk
Application.mk
com_sobot_chat_utils_SobotUtil.h
md5.c
md5.h
sobot.c

6. 打开命令窗口，进入jni文件夹，执行命令 **ndk-build** ，会自动生成一个libs文件夹。里边的 .so 文件供调用

注意：有时候出现找不到ndk-build，1、看下环境变量里有没ndk路径， 2、执行source .bash_profile，然后在进入jni文件夹下，执行ndk-build


三、调用生成的 .so文件
1. 把so文件复制到module下的libs
2. build.gradle中andoid下添加
sourceSets{
        main(){
            jniLibs.srcDirs = ['libs']
        }
}
3.写工具类加载sobot.so 库调用对应的native 方法
public class SobotUtil {
    static {
        System.loadLibrary("sobot");
    }

    public static native String getSign(String a, String b, String c, String d, String e);

}
 
