Closed7

flutterのffiでC++ライブラリを呼び出す(Android)

nabeyangnabeyang

ABIの確認

$ ~/Library/Android/sdk/platform-tools/adb devices
List of devices attached
${ID}	device

${ID}の部分に端末のIDが出るのでadbで接続する。

$  ~/Library/Android/sdk/platform-tools/adb -s ${ID} shell 

ABIを確認

$ getprop | grep cpu
nabeyangnabeyang

ビルド

androidは動的ライブラリが使えるので、STATICを除きます。

core/CMakeLists.txt
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 875e492..f49efa2 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -434,8 +434,8 @@ source_group (Sources\\qrcode FILES ${QRCODE_FILES})
 source_group (Sources\\textcodec FILES ${TEXT_CODEC_FILES})
 
 find_package (Threads)
-
-add_library (ZXing STATIC
+# ios: STATIC
+add_library (ZXing
     ${COMMON_FILES}
     ${AZTEC_FILES}
     ${DATAMATRIX_FILES}

ライブラリをビルドします。android sdk内のcmakeを使います。

/Users/nabeyang/Library/Android/sdk/cmake/3.18.1/bin/cmake \
      -DCMAKE_TOOLCHAIN_FILE="~/Library/Android/sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake" \
      -DANDROID_NDK="~/Library/Android/sdk/ndk/22.1.7171670"  \
      -DCMAKE_BUILD_TYPE=Debug                     \
      -DANDROID_ABI="armeabi-v7a with NEON"         \
      -DBUILD_WRITERS=OFF \
      -DBUILD_EXAMPLES=OFF \
      -DBUILD_BLACKBOX_TESTS=OFF \
      -B bin/android_v7a \
      .
/Users/nabeyang/Library/Android/sdk/cmake/3.18.1/bin/cmake --build ./bin/android_v7a

arm64-v8aをビルドするときは -DANDROID_ABI="arm64-v8a"に変えるだけです。iOSと違うところは、ビルド前にリリース用かデバッグ用なのかを指定するところです(iOSはcmake --buildのときに指定)。

nabeyangnabeyang

flutter pluginを作成

androidだけ作る場合はこうすればOKです。

$ flutter create --platforms=android --template=plugin zxing_sample
nabeyangnabeyang

ライブラリを設置

先程ビルドしたライブラリを次のように設置します。

$tree  /path/to/project/android/libs
android/libs
├── arm64-v8a
│   └── libZXing.so
└── armeabi-v7a
    └── libZXing.so

build.gradleにライブラリパスを追加します。

build.gradle
android {
    compileSdkVersion 30

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
        main.jniLibs.srcDir "${project.projectDir.path}/libs"
    }
nabeyangnabeyang

ライブラリのロード

DynamicLibraryの初期化の仕方がiOSと異なるだけで、それ以降は同じです。

import 'dart:ffi'; // For FFI
import 'package:ffi/ffi.dart';
final DynamicLibrary zxingLib = DynamicLibrary.open("libZXing.so");
final void Function(Pointer<Utf8>, Pointer<Utf8>) loadBarcode =
zxingLib
    .lookup<NativeFunction<Void Function(Pointer, Pointer)>>("load_barcode")
    .asFunction();

exampleからの呼び出し

info.plistの編集が要らない以外はiOS版と同じです。
https://zenn.dev/nnabeyang/scraps/66dcfeef4084de#comment-755e32c1135d3b

このスクラップは2021/04/26にクローズされました