Simple Use of android studio JNI/NDK

Posted by myitanalyst on Sun, 19 May 2019 20:35:24 +0200

See android sdk26(8.0) when it was recently updated

NDK 15.2.4203891

So I updated it. I didn't expect to dry up the D disk directly. I could only delete some files from the D disk, including the android-ndk-r13b file.
By the way, run it again and record it. Although there are not many opportunities to contact JNI development, but occasionally involved, for example, we put the ASE secret key of login into jni, which improves security, and it is more difficult to crack so files than java.

1. Environmental Configuration

In addition to updating the NDK mentioned above, CMake, LLDB are also required.

2. Create a java file that needs to be invoked by Java - JNIUtil

public class NdkJniUtils {

    public native String getUserKey(String signature);
    public native String getWeixinAppKey(String signature);
}

Then call it directly elsewhere. Here's a case of use:

NdkJniUtils util = new NdkJniUtils();
util.getUserKey(PackageUtil.getSignature(this)); //This Output Input Packet Value
==================
public class PackageUtil {
    public static String getSignature(Context context)
    {
        try {
            /** Get package information with signature in specified package name through package manager**/
            PackageInfo packageInfo = null;
            try {
                packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            /******* Get the signature array ****** from the returned package information*/
            Signature[] signatures = packageInfo.signatures;
            /******* Circular traversal signature array splicing application signature*******/
            return signatures[0].toCharsString();
            /************** Get Signature Applied********************/
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

3. Editing c file

Then the build project gets the intermediate file, and we focus on the. class file. The class file generated after compiling OK is in the following directory of AS project:

NDKApplication\app\build\intermediates\classes\debug

Then the next step is to use javah to generate the corresponding. h header file according to the generated class file.
Open the Terminal tab of AS and enter the app folder of the project by default. I enter the following command on the windows platform to jump to the class intermediate file generation path:

xxxxx\app> cd build\intermediates\classes\debug

Then execute the following javah command to generate the h file:

xxxxx\debug> javah -jni com.xxx.cn.utility.secure.NdkJniUtils

After execution, you can see the generated. h header file in the folder NDKApplication app build intermediates classes debug.

xxx_NdkJniUtils.h

Its contents are as follows:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xxx_cn_utility_secure_NdkJniUtils */

#ifndef _Included_com_xxx_cn_utility_secure_NdkJniUtils
#define _Included_com_xxx_cn_utility_secure_NdkJniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_xxx_cn_utility_secure_NdkJniUtils
 * Method:    getUserKey
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_xxx_cn_utility_secure_NdkJniUtils_getUserKey
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_xxx_cn_utility_secure_NdkJniUtils
 * Method:    getWeixinAppKey
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_xxx_cn_utility_secure_NdkJniUtils_getWeixinAppKey
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

Create a new directory named jni under the main directory of the project, and then cut the. h file you just created. Create a new cpp file in the jni directory and name it at will. My name is jniUtil.cpp. Then edit the code as follows:

#include "com_xxx_cn_utility_secure_NdkJniUtils.h"
#include <string.h>

//http api To grant authorization key ,Provided by the server
const char* WEIXIN_APP_SECRET = "xxx";

//user aes Encryption and decryption key
const char* USER_KEY = "aaa";

//Released app autograph,Only in accordance with this signature app Only then will legal authorization be returned key,Prevent so Files are stolen by unknown applications
const char* RELEASE_SIGN ="xxx";

JNIEXPORT jstring JNICALL Java_com_xxx_cn_utility_secure_NdkJniUtils_getWeixinAppKey
  (JNIEnv* env, jobject obj, jstring signStrng) {

    const char *str = (env)->GetStringUTFChars(signStrng, 0);
    int ret=strcmp(str,RELEASE_SIGN);
    env->ReleaseStringUTFChars(signStrng, str);

    return ret==0?(env)->NewStringUTF(WEIXIN_APP_SECRET):(env)->NewStringUTF("");
}
JNIEXPORT jstring JNICALL Java_com_xxx_cn_utility_secure_NdkJniUtils_getUserKey
        (JNIEnv* env, jobject obj, jstring signStrng) {

  const char *str = (env)->GetStringUTFChars(signStrng, 0);
  int ret=strcmp(str,RELEASE_SIGN);
  env->ReleaseStringUTFChars(signStrng, str);

  return ret==0?(env)->NewStringUTF(USER_KEY):(env)->NewStringUTF("");
}

Next, add the NDK path (the NDK downloaded above) to the local.properties file of the project, similar to the SDK path in it:

ndk.dir=D\:\\Android\\Android\\sdk\\ndk-bundle
sdk.dir=D\:\\Android\\Android\\sdk

Next, set the library file name (the generated so file name) in build.gradle in the app module directory. Find defaultConfig in the gradle file and add the following:

defaultConfig {
    ......
    ndk{
        moduleName "JniUtil"         //The generated so name is the same as the name in Ndk JniUtils
        abiFilters "armeabi", "armeabi-v7a", "x86"  //The output specifies so libraries under three abi architectures. At present, it may or may not be.
    }
}

Now that the name of the so library has been generated, add static initialization load code to the NdkJniUtils java file of the code, and add the following:

public class JniUtil {

    public native String getUserKey(String signature);
    public native String getWeixinAppKey(String signature);

    static {
        System.loadLibrary("JniUtil");
    }
}

OK, so far as the coding and setup of NDK JNI under AS is concerned, then the compilation project will run.
Running, I went wrong:

Error:Execution failed for task ':libtermexec:compileReleaseNdk'.
> Error: Your project contains C++ files but it is not using a supported native build system.
Consider using CMake or ndk-build integration with the stable Android Gradle plugin:
https://developer.android.com/studio/projects/add-native-code.html
or use the experimental plugin:
https://developer.android.com/studio/build/experimental-plugin.html.

You need to add gradle.properties under the project:

android.useDeprecatedNdk=true

Topics: Android Java SDK Gradle