轉載請以連接形式標明出處: 本文出自:103style的博客html
本文操做以 Android Studio 3.4.2 版本爲例android
NDK開發文章彙總git
咱們app作網絡請求的時候通常都會添加校驗位,校驗位的加密方法能夠經過jni實現,提供安全係數。github
Encryptor
類,編寫對應的測試代碼:public class Encryptor {
private static final String TAG = "Encryptor";
static {
System.loadLibrary("encryptor");
}
private final String BASE_URL = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
/**
* 加密
*
* @param normalPath 文件路徑
* @param encryptPath 加密以後的文件路徑
*/
public native static void encryption(String normalPath, String encryptPath);
/**
* 解密
*
* @param encryptPath 加密以後的文件路徑
* @param decryptPath 解密以後的文件路徑
*/
public native static void decryption(String encryptPath, String decryptPath);
/**
* 建立文件
*
* @param normalPath 文件路徑
*/
private native void createFile(String normalPath);
/**
* 測試加解密
*/
public void test() {
String fileName = "testJni.txt";
String encryptPath = encryption(fileName);
decryption(encryptPath);
}
/**
* 加密
*/
public String encryption(String fileName) {
String normalPath = BASE_URL + fileName;
File file = new File(normalPath);
if (!file.exists()) {
createFile(normalPath);
}
String encryptPath = BASE_URL + "encryption_" + fileName;
Encryptor.encryption(normalPath, encryptPath);
Log.d(TAG, "加密完成了...");
return encryptPath;
}
/**
* 解密
*/
public void decryption(String encryptPath) {
if (!new File(encryptPath).exists()) {
Log.d(TAG, "解密文件不存在");
return;
}
String decryptPath = encryptPath.replace("encryption_", "decryption_");
Encryptor.decryption(encryptPath, decryptPath);
Log.d(TAG, "解密完成了...");
}
}
複製代碼
encryptor.cpp
CMakeLists.txt
:add_library(encryptor
SHARED
src/main/cpp/encryptor.cpp)
target_link_libraries(
encryptor
${log-lib})
複製代碼
fopen()函數介紹。安全
#include <cstdio>
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_Encryptor_createFile(JNIEnv *env, jobject instance,
jstring normalPath_) {
//獲取字符串保存在JVM中內存中
const char *normalPath = env->GetStringUTFChars(normalPath_, nullptr);
//打開 normalPath wb:只寫打開或新建一個二進制文件;只容許寫數據
FILE *fp = fopen(normalPath, "wb");
//把字符串寫入到指定的流 stream 中,但不包括空字符。
fputs("Hi, this file is created by JNI, and my name is 103style.", fp);
//關閉流 fp。刷新全部的緩衝區
fclose(fp);
//釋放JVM保存的字符串的內存
env->ReleaseStringUTFChars(normalPath_, normalPath);
}
複製代碼
#include <android/log.h>
#include <cstdio>
#include <cstring>
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"Encryptor",FORMAT,##__VA_ARGS__);
char password[] = "103style";
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_Encryptor_encryption(JNIEnv *env, jclass type, jstring normalPath_,
jstring encryptPath_) {
//獲取字符串保存在JVM中內存中
const char *normalPath = env->GetStringUTFChars(normalPath_, nullptr);
const char *encryptPath = env->GetStringUTFChars(encryptPath_, nullptr);
LOGE("normalPath = %s, encryptPath = %s", normalPath, encryptPath);
//rb:只讀打開一個二進制文件,容許讀數據。
//wb:只寫打開或新建一個二進制文件;只容許寫數據
FILE *normal_fp = fopen(normalPath, "rb");
FILE *encrypt_fp = fopen(encryptPath, "wb");
if (normal_fp == nullptr) {
LOGE("%s", "文件打開失敗");
return;
}
//一次讀取一個字符
int ch = 0;
int i = 0;
size_t pwd_length = strlen(password);
while ((ch = fgetc(normal_fp)) != EOF) { //End of File
//寫入(異或運算)
fputc(ch ^ password[i % pwd_length], encrypt_fp);
i++;
}
//關閉流 normal_fp和encrypt_fp。刷新全部的緩衝區
fclose(normal_fp);
fclose(encrypt_fp);
//釋放JVM保存的字符串的內存
env->ReleaseStringUTFChars(normalPath_, normalPath);
env->ReleaseStringUTFChars(encryptPath_, encryptPath);
}
複製代碼
#include <android/log.h>
#include <cstdio>
#include <cstring>
#define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"Encryptor",FORMAT,##__VA_ARGS__);
char password[] = "103style";
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_Encryptor_decryption(JNIEnv *env, jclass type, jstring encryptPath_,
jstring decryptPath_) {
////獲取字符串保存在JVM中內存中
const char *encryptPath = env->GetStringUTFChars(encryptPath_, nullptr);
const char *decryptPath = env->GetStringUTFChars(decryptPath_, nullptr);
LOGE("encryptPath = %s, decryptPath = %s", encryptPath, decryptPath);
//rb:只讀打開一個二進制文件,容許讀數據。
//wb:只寫打開或新建一個二進制文件;只容許寫數據
FILE *encrypt_fp = fopen(encryptPath, "rb");
FILE *decrypt_fp = fopen(decryptPath, "wb");
if (encrypt_fp == nullptr) {
LOGE("%s", "加密文件打開失敗");
return;
}
int ch;
int i = 0;
size_t pwd_length = strlen(password);
while ((ch = fgetc(encrypt_fp)) != EOF) {
fputc(ch ^ password[i % pwd_length], decrypt_fp);
i++;
}
//關閉流 encrypt_fp 和 decrypt_fp。刷新全部的緩衝區
fclose(encrypt_fp);
fclose(decrypt_fp);
//釋放JVM保存的字符串的內存
env->ReleaseStringUTFChars(encryptPath_, encryptPath);
env->ReleaseStringUTFChars(decryptPath_, decryptPath);
}
複製代碼
private void testEncryptor() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x1024);
return;
}
}
new Encryptor().test();
}
複製代碼
執行程序會在 手機根目錄 生成如下三個文件:bash
testJni.txt
:原文件encryption_testJni.txt
:加密以後的文件decryption_testJni.txt
:解密以後的文件demo地址: https://github.com/103style/NDKDoc/tree/master/HelloNDK網絡
若是以爲不錯的話,請幫忙點個讚唄。app
以上函數
掃描下面的二維碼,關注個人公衆號 Android1024, 點關注,不迷路。 測試