正在工作時(shí),突然被同事問(wèn)到:“秘鑰放在哪里比較安全活翩,X總說(shuō)我這樣寫不行烹骨。”
其實(shí)很多時(shí)候材泄,app都需要用到一些敏感的數(shù)據(jù)沮焕,例如加密的秘鑰、一些渠道的APP_ID等拉宗,但如果被別人反編譯拿到這些數(shù)據(jù)峦树,就很有可能會(huì)造成損失辣辫。
那怎么增加被獲取的難度?就是將這些數(shù)據(jù)放到C/C++的文件內(nèi)魁巩,然后將其生成為so庫(kù)急灭,交給app應(yīng)用層去調(diào)用。因?yàn)镃/C++反匯編的難度谷遂,怎么都比反編譯一個(gè)apk要難葬馋,這樣就能更加有效地保證敏感數(shù)據(jù)的安全了。
一肾扰、工具準(zhǔn)備
下載AndroidStudio畴嘶,并確保下載好了NDK和CMake。二集晚、新建一個(gè)項(xiàng)目
普通項(xiàng)目也行窗悯,C++項(xiàng)目也行,由于C++項(xiàng)目會(huì)自動(dòng)配置CMakeList文件甩恼,所以我這里直接創(chuàng)建C++項(xiàng)目了蟀瞧。三、編寫JNI工具類
創(chuàng)建一個(gè)Java類条摸,并在內(nèi)部定義你需要的方法悦污。
public class MyJavaJNI {
static {
System.loadLibrary("JniTest");
}
public native String getKeyStr();
}
四、將工具類編譯為class文件
首先钉蒲,在Android Studio中打開(kāi)terminal切端,在這里打開(kāi)的,其實(shí)就是終端顷啼,并不需要管環(huán)境配置踏枣,因?yàn)锳ndroid Studio其實(shí)已經(jīng)都關(guān)聯(lián)好了。然后钙蒙,跳轉(zhuǎn)到工具類所在的目錄茵瀑,并編譯文件,之后再返回到j(luò)ava目錄躬厌。
cd com/cjy/solibrarydemo
javac MyJavaJNI.java
cd..
cd..
cd..
最后马昨,通過(guò)命令javah -jni com.cjy.solibrarydemo.MyJavaJNI生成C文件。完成后扛施,你會(huì)看到跟下圖差不多的文件結(jié)構(gòu)鸿捧。五、創(chuàng)建JNI文件夾疙渣,并且把第四步中的C文件放進(jìn)去匙奴。
右鍵app項(xiàng)目,new出JNI文件夾妄荔。六、修改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庫(kù)
先配置你需要生成的CPU架構(gòu),在build.gradle中增加配置項(xiàng)笋颤。
externalNativeBuild {
cmake {
cppFlags ''
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
開(kāi)始生成so庫(kù)。
八、使用so庫(kù)
一般的情況下阱缓,都是自己的項(xiàng)目非凌,那使用的做法就很簡(jiǎn)單,將所有架構(gòu)的so文件荆针,復(fù)制到libs文件夾中敞嗡,然后在你需要調(diào)用方法的地方直接調(diào)用就行了。
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()
}
但是如果是需要提供給別人用的航背,那就不能這樣了喉悴。因?yàn)閯e人復(fù)制了你的so文件之余,還需要新建工具類的全路徑玖媚,一模一樣的那種箕肃,再?gòu)?fù)制工具類(MyJavaJNI.java)進(jìn)去,才能正常使用今魔。
這時(shí)候我們應(yīng)該將工具類打包成aar或者jar文件勺像,一起提供給別人使用,這樣別人就不用那么麻煩了错森。