LoginSignup
0
0

android ndkで外部ライブラリを使用する方法

Posted at

多分もっと良い方法があると思うが、とりあえず動いた方法

ライブラリの準備

  • ソースコードを取ってきて
git clone https://github.com/ARMmbed/mbedtls.git
  • ビルド
cd mbedtls
export NDK_HOME=${HOME}/Android/Sdk/ndk/26.1.10909125
for a in arm64-v8a armeabi-v7a x86 x86_64
do mkdir build_${a}; cd build_${a}
cmake -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI=${a} -DANDROID_PLATFORM=android-31 .. 
make
cd ..
done
  • コピー
for a in arm64-v8a armeabi-v7a x86 x86_64
do mkdir -p /path/to/android/app/src/main/cpp/${a}
for b in `find build_$a -name *.a`
do cp $b /path/to/android/app/src/main/cpp/${a}/
done
done

android側

ファイル作成とか修正

  • app/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)

set(MBEDTLS_DIR "${CMAKE_SOURCE_DIR}/../../../../../oss/mbedtls/")

add_library(mbedtls STATIC IMPORTED)
set_target_properties(mbedtls PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/${ANDROID_ABI}/libmbedtls.a)

add_library(mbedcrypto STATIC IMPORTED)
set_target_properties(mbedcrypto PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/${ANDROID_ABI}/libmbedcrypto.a)

add_library(mbedx509 STATIC IMPORTED)
set_target_properties(mbedx509 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/${ANDROID_ABI}/libmbedx509.a)

include_directories(${MBEDTLS_DIR}/include)

add_library(native-lib SHARED ${CMAKE_SOURCE_DIR}/native-lib.cpp)

target_link_libraries(native-lib mbedtls mbedcrypto mbedx509)

app/build.gradle

diff --git a/android/app/build.gradle b/android/app/build.gradle
index e8bd5e3..1e6cc14 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -81,6 +81,14 @@ android {
         targetSdkVersion rootProject.ext.targetSdkVersion
         versionCode 1
         versionName "1.0"
+        ndk {
+            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86'
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "src/main/cpp/CMakeLists.txt"
+        }
     }
     signingConfigs {
         debug {
  • app/src/main/cpp/native-lib.cpp
    クラス名は使用する場所に合わせる
#include <jni.h>
#include <string>
#include "mbedtls/aes.h"

extern "C"
    JNIEXPORT void JNICALL
    Java_com_sample_SampleClass_encryptAES(JNIEnv *env, jobject thiz, jbyteArray inputData,
                                         jbyteArray key, jbyteArray outputData) {

    // Initialize AES context
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);

    // Convert Java byte arrays to C arrays
    jbyte* input = env->GetByteArrayElements(inputData, nullptr);
    jbyte* keyData = env->GetByteArrayElements(key, nullptr);

    // Set the AES key
    mbedtls_aes_setkey_enc(&aes, (const unsigned char *) keyData, 128);

    // Encrypt the data
    size_t length = env->GetArrayLength(inputData);
    jbyte* output = env->GetByteArrayElements(outputData, nullptr);

    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, (const unsigned char *) input, (unsigned char *) output);

    // Release the AES context
    mbedtls_aes_free(&aes);

    // Release the Java byte arrays
    env->ReleaseByteArrayElements(inputData, input, 0);
    env->ReleaseByteArrayElements(key, keyData, 0);
    env->ReleaseByteArrayElements(outputData, output, 0);
}


  • app/src/main/java/com/sample/SampleClass.java
public class SampleClass {
    static {
        System.loadLibrary("native-lib");
    }

    public native void encryptAES(byte[] inputData, byte[] key, byte[] output);

    public void test() {
        byte[] data = "Hello, World!".getBytes();
        byte[] key = "1234567890123456".getBytes();
        byte[] output = new byte[data.length];
        encryptAES(data, key, output); 
        // omit log output

ビルド

./gradlew assemble

サンプル出力

48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21  -> D5 C6 3B E1 59 57 0E E7 70 38 46 F9 D8
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0