Edited at

Androidアプリの開発中にUnsatisfiedLinkErrorで詰まった話(ネイティブライブラリ周り)


Androidでネイティブライブラリ(VoiceText)を使った時にハマった話


はじめに

新卒専用 Advent Calendar 2017 15日目の記事です💁


なんのはなし

本当はSwift4でiOSアプリを作りたかったんだけど間に合いそうにないので、急遽Androidアプリ開発の仕事をしてたときのハマったことについて書きます。

(いつか投稿しようと思って、メモ書きしててよかった😅)

これからネイティブライブラリを使ったAndroid開発している人の参考になればと思います。😊


症状

実機では動く処理がエミュレータでは落ちる

(java.lang.UnsatisfiedLinkErrorの発生)


原因

端末
アーキテクチャ

実機
arm系

シミュレータ
x86

使用していたネイティブライブラリがx86非対応だった。

アプリが落ちる時に java.lang.UnsatisfiedLinkError としか出力されなかった為、つまった。

UnsatisfiedLinkError (Java Platform SE 7 ) についてはコチラ


解決策

ネイティブ ライブラリの特定の ABI 設定のみをビルドおよびパッケージ化する

build.gradle ファイルを編集

android{

...
defaultConfig {
...
// 以下を追加
ndk {
abiFilters "arm64-v8a", "armeabi-v7a", "armeabi"
}
}
...
}

参考リンク:プロジェクトへのC/C++コードの追加

以下、蛇足


Android CPU/ABIについて

Androidのシミュレータ作成するときに、x86 とか arm64_v8a とかいう文字を見ませんでした?

とりあえず適当にrecommendedのやつ( x86 )選べばいいか😉 なんてやってませんか?

自分はやってました😅

そもそも、この x86 とか armXXX って何?って思って色々調べたら、ABI(ApplicationBinaryInterface)の事らしい(それすらも知らなかった)

AndroidのABIについては、以下の記事がわかりやすかったです。

【本当に32ビット?】Android端末の CPU の ABI を特定する

まとめると、


  • 端末ごと(CPU)ごとに違うABIが使われてる


    • GalaxyS7は ARM64 (ARM系統) 

    • ASUS Zenphone2は x86 を使っている とか



標題のエラーが出た時もしやと思って調べてみたら、これが原因でした。


ネイティブライブラリのインポートの仕方

ネイティブライブラリをインポートするやり方もメモってたのでついでに書きます。


やり方

*.soファイルがあると思うのでそれを適切なパスへ配置する

1. app/src/main/jniLibs配下へアーキテクチャごとにフォルダを作って配置


  • 例 x86向けhoge_foo_bar.soファイルを配置したい場合


    • app/src/main/jniLibs/x86/hoge_foo_bar.so



2. インポート文を書く

// build.gradle

android{
...
sourceSets {
main {
// ネイティブライブラリをインポートする用のディレクトリ設定
jniLibs.srcDirs = ['src/main/jniLibs','src/main/jniLibs/']
}
}
}


まとめ


  • UnsatisfiedLinkErrorが発生した時は以下を確認する


    • ネイティブライブラリが正しくインポートされているか

    • ネイティブライブラリが実行した端末のアーキテクチャに対応してるか



  • VoiceTextはARMのみ対応でx86は非対応 (2017/12/14現在)

  • シミュレータのABIをarmにすると遅くてどうしようもないので、素直に端末買いましょう


その他参考リンク

https://qiita.com/KawabataLemon/items/c9bd851deacc72a7458a

http://software.fujitsu.com/jp/manual/manualfiles/M050000/B1WN5031/03/msg43/msg09889.htm

https://android.benigumo.com/20161222/android_cpu_abi_arm_x86/