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"
}
}
...
}
以下、蛇足
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
を使っている とか
- GalaxyS7は
標題のエラーが出た時もしやと思って調べてみたら、これが原因でした。
ネイティブライブラリのインポートの仕方
ネイティブライブラリをインポートするやり方もメモってたのでついでに書きます。
やり方
*.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にすると遅くてどうしようもないので、素直に端末買いましょう
その他参考リンク