Android JNI調用c語言加密程序

在這篇博客中,我將利用NDK調用JNI來使用本地c語言實現的一個簡單的加密程序,主要是爲了熟悉NDK和JNI的使用方法,希望可以讓後來人少踩一些坑。

系統環境

Android Studio 2.3.3
jdk1.8.0
android-ndk-r14b-windows-x86_64

配置NDK環境

下載NDK和配置環境變量在此不做贅述,不會的可以自行百度
在Android Studio中File–>ProjectStructure–>SDK Location配置“Android NDK Location”如下圖:

配置gradle.properties和build.gradle文件

在項目目錄下gradle.properties文件中加入

android.useDeprecatedNdk=true

修改app–>build.gradle,添加以下內容:
在defaultConfig中添加ndk項,這裏moduleName是將來生成.so文件的名字,abiFilters是生成指定平臺的so文件,如果不寫abiFilters會生成所有平臺的so文件

ndk {
    moduleName "Crypto"
    abiFilters "armeabi"
}

在buildTypes中添加sourceSets項,配置so文件存放位置

sourceSets {
    main {
        jni.srcDirs = ['libs']
    }
}

添加native方法

public class Crypto {

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

    public native String encrypt(String prim);
    public native String decrypt(String code);

}

這裏我們添加兩個方法供以後使用,注意這裏loadLibrary要和build.gradle中moduleName一致

使用javah生成對應.h頭文件

在Android Studio下方Terminal進入java路徑(直接將文件夾拖到命令行就進入該目錄了),如果沒有Terminal,從View–>Tool Windows–>Terminal打開即可。
輸入命令javah -jni 包名.類名

javah -jni com.example.administrator.ndk_crypto.Crypto

生成的com_example_administrator_ndk_crypto_Crypto.h如下:

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

#ifndef _Included_com_example_administrator_ndk_crypto_Crypto
#define _Included_com_example_administrator_ndk_crypto_Crypto
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_administrator_ndk_crypto_Crypto
 * Method:    encrypt
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_administrator_ndk_1crypto_Crypto_encrypt
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_example_administrator_ndk_crypto_Crypto
 * Method:    decrypt
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_administrator_ndk_1crypto_Crypto_decrypt
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

創建jni目錄和.mk文件

1、在main目錄下新建jni目錄:
New–>Forder–>JNI Forder
2、將剛生成的.h文件複製到jni文件夾中
3、創建Crypto.c文件,引入頭文件,並實現其中的方法。

#include "com_example_administrator_ndk_crypto_Crypto.h"

JNIEXPORT jstring JNICALL Java_com_example_administrator_ndk_1crypto_Crypto_encrypt
  (JNIEnv * env, jobject obj, jstring str) {
        char *prim = (*env)->GetStringUTFChars(env, str, 0);
        char code[100];
        int i,n,len;
        char temp_char,trans_char;
        int temp_num,trans_num;
        len = strlen(prim);
        for (int i = 0; i < len; ++i)
        {
            code[i] = prim[i] + 1;
        }

        for(i = 0;i < len;i++) {
            temp_char = prim[i];                   //Consider about the corresponding number of character
            if (temp_char <= 'z' && temp_char >= 'a')
                temp_num = temp_char - 'a' + 1;
            else if (temp_char <= 'Z' && temp_char >= 'A')
                temp_num = temp_char - 'A' + 27;

            trans_num = temp_num*3 % 52;

            if (trans_num > 26 && trans_num <= 52)         //Transform number to character
                trans_char = 'A' + trans_num - 27;
            else if (trans_num > 0 && trans_num <= 26)
                trans_char = 'a' + trans_num - 1;

            code[i] = trans_char;
        }
        code[len] = '\0';
    return (*env)->NewStringUTF(env, code);
  }

JNIEXPORT jstring JNICALL Java_com_example_administrator_ndk_1crypto_Crypto_decrypt
  (JNIEnv * env, jobject obj, jstring str) {
      char *code = (*env)->GetStringUTFChars(env, str, 0);
      char prim[100];
      int i,n,len;
      char temp_char,trans_char;
      int temp_num,trans_num;
      len = strlen(code);

      for(i = 0;i < len;i++) {
          temp_char = code[i];             //Consider about the corresponding digit of character
          if (temp_char <= 'z' && temp_char >= 'a')
              temp_num = temp_char - 'a' + 1;
          else if (temp_char <= 'Z' && temp_char >= 'A')
              temp_num = temp_char - 'A' + 27;

          n = temp_num % 3;  //Mode 3 and compute primitive number
          switch(n) {
          case 0:
              trans_num = temp_num/3;
              break;
          case 1:
              trans_num = 35 + temp_num/3;
              break;
          case 2:
              trans_num = 18 + temp_num/3;
              break;
          default:
              break;
          }
             //Transform number to character
          if (trans_num > 26 && trans_num <= 52)
              trans_char = 'A' + trans_num - 27;
          else if (trans_num > 0 && trans_num <= 26)
              trans_char = 'a' + trans_num - 1;

          prim[i] = trans_char;
      }
      prim[len] = '\0';
    return (*env)->NewStringUTF(env, prim);
  }

4、創建Android.mk文件
LOCAL_SRC_FILES爲c文件名,LOCAL_MODULE爲so文件,應該與moduleName一致

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := Crypto
LOCAL_SRC_FILES := Crypto.c

include $(BUILD_SHARED_LIBRARY)

5、創建Application.mk文件
APP_ABI := armeabi表示只支持armeabi架構的jni,如需其他架構可在後面追加

APP_CFLAGS += -Wno-error=format-security
APP_ABI := armeabi

編譯so文件

在Terminal進入main目錄下,執行ndk-build

在main/libs中會生成.so文件

在main目錄下新建一個jniLibs文件夾,將libs下面的文件複製到jniLibs中,編譯運行即可。

運行結果

源代碼

http://download.csdn.net/download/baidu_34045013/10192722
https://github.com/Caesar233/Android-NDK-Crypto

發佈了56 篇原創文章 · 獲贊 118 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章