美文网首页实用
Android-通过JNI和NDK生成so库

Android-通过JNI和NDK生成so库

作者: 超人TIGA | 来源:发表于2022-06-05 22:49 被阅读0次

    正在工作时,突然被同事问到:“秘钥放在哪里比较安全,X总说我这样写不行。”

    其实很多时候,app都需要用到一些敏感的数据,例如加密的秘钥、一些渠道的APP_ID等,但如果被别人反编译拿到这些数据,就很有可能会造成损失。
    那怎么增加被获取的难度?就是将这些数据放到C/C++的文件内,然后将其生成为so库,交给app应用层去调用。因为C/C++反汇编的难度,怎么都比反编译一个apk要难,这样就能更加有效地保证敏感数据的安全了。

    一、工具准备
    下载AndroidStudio,并确保下载好了NDK和CMake。 image.png
    二、新建一个项目
    普通项目也行,C++项目也行,由于C++项目会自动配置CMakeList文件,所以我这里直接创建C++项目了。 image.png
    三、编写JNI工具类

    创建一个Java类,并在内部定义你需要的方法。


    image.png
    public class MyJavaJNI {
         static {
             System.loadLibrary("JniTest");
         }
    
         public native String getKeyStr();
    }
    
    四、将工具类编译为class文件
    首先,在Android Studio中打开terminal,在这里打开的,其实就是终端,并不需要管环境配置,因为Android Studio其实已经都关联好了。 image.png

    然后,跳转到工具类所在的目录,并编译文件,之后再返回到java目录。

    cd com/cjy/solibrarydemo
    
    javac MyJavaJNI.java
    
    cd..
    cd..
    cd..
    
    最后,通过命令javah -jni com.cjy.solibrarydemo.MyJavaJNI生成C文件。完成后,你会看到跟下图差不多的文件结构。 image.png
    五、创建JNI文件夹,并且把第四步中的C文件放进去。
    右键app项目,new出JNI文件夹。 image.png 将C文件放进去,并将后缀名改为.c。 image.png
    六、修改CMakeList文件并编写方法。

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.18.1)
    set(srcDir ${CMAKE_SOURCE_DIR}/../..)
    project("solibrarydemo")
    
    add_library(
            javaJni
    
            SHARED
    
            ${srcDir}/main/jni/com_cjy_solibrarydemo_MyJavaJNI.c
    )
    
    add_library( # Sets the name of the library.
            solibrarydemo
    
            # Sets the library as a shared library.
            SHARED
    
            # Provides a relative path to your source file(s).
            native-lib.cpp)
    
    find_library( # Sets the name of the path variable.
            log-lib
    
            # Specifies the name of the NDK library that
            # you want CMake to locate.
            log)
    
    target_link_libraries( # Specifies the target library.
            solibrarydemo
            javaJni
            # Links the target library to the log library
            # included in the NDK.
            ${log-lib})
    

    com_cjy_solibrarydemo_MyJavaJNI.c

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_cjy_solibrarydemo_MyJavaJNI */
    
    #ifndef _Included_com_cjy_solibrarydemo_MyJavaJNI
    #define _Included_com_cjy_solibrarydemo_MyJavaJNI
    
    #define keyStr "123456789"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_cjy_solibrarydemo_MyJavaJNI
     * Method:    getKeyStr
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring
    
    JNICALL Java_com_cjy_solibrarydemo_MyJavaJNI_getKeyStr
      (JNIEnv *env, jclass objt){
        return (*env)->NewStringUTF(env,keyStr);
    };
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    七、生成so库

    先配置你需要生成的CPU架构,在build.gradle中增加配置项。

    externalNativeBuild {
                cmake {
                    cppFlags ''
                    abiFilters "arm64-v8a", "armeabi-v7a"
                }
            }
    

    开始生成so库。


    image.png 查看结果: image.png 这里的libjavaJni.so,就是我们需要的so库了。
    八、使用so库

    一般的情况下,都是自己的项目,那使用的做法就很简单,将所有架构的so文件,复制到libs文件夹中,然后在你需要调用方法的地方直接调用就行了。

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            // Example of a call to a native method
            binding.sampleText.text = MyJavaJNI.getKeyStr()
        }
    

    但是如果是需要提供给别人用的,那就不能这样了。因为别人复制了你的so文件之余,还需要新建工具类的全路径,一模一样的那种,再复制工具类(MyJavaJNI.java)进去,才能正常使用。
    这时候我们应该将工具类打包成aar或者jar文件,一起提供给别人使用,这样别人就不用那么麻烦了。

    相关文章

      网友评论

        本文标题:Android-通过JNI和NDK生成so库

        本文链接:https://www.haomeiwen.com/subject/gchqmrtx.html