Androidアプリ開発中に、外からとってきたsoファイルを使いたいとする。(openCVとか)
大体、armeabi-v7a用とかx86用とか書いてあるけど気にせず全部jniLibs直下にコピーする。
実際、どの端末でどのsoファイルが動いてるかよく知らない。そもそもarmとかx86とか何?
そんな自分のための記事。
#ARM? X86? MIPS?
android端末のCPUに適用される命令セットアーキテクチャ(または、CPUそのもの)の名称を指す。
armであれば、arm社のarmアーキテクチャが
X86なら、Intel社のIntel 8086、またその後方互換のアーキテクチャ、
MIPSなら、ミップス・コンピュータシステムズ(現ミップス・テクノロジーズ)社のアーキテクチャがそれぞれ適用されているCPUであるということになる。
#命令セットアーキテクチャが違うと?
C/C++言語で書いたコードは、ターゲットとする命令セットアーキテクチャに対してコンパイルし、専用の実行バイナリファイルを作成する。
つまり、他の命令セットアーキテクチャのためにコンパイルされたバイナリファイルは動かない。なので、openCVなどのオープンソースはどのCPUを積んだ端末でも動くよう、それぞれの命令セットアーキテクチャに合わせたsoファイルを用意している。
OpenCV4Android SDK
androidにおいては、その命令セットアーキテクチャの違いをABIという定義で管理する。
#ABIとは?
Application Binary Interfaceの略
正式な定義は、
"ABI は、アプリケーションのマシンコードが実行時にシステムとやり取りする方法を詳細に定義したもの"
Android Developers->NDK ABI管理
適当な覚え方は、
端末のCPUと命令セットに応じて定義するディレクトリの名称。soファイルを入れるところ。
端末Aでは動いたのに、端末Bでは"Fatal Exception: java.lang.UnsatisfiedLinkError"でアプリが落ちたみたいなとき、端末Bに対応するABIのsoファイルを入れてなかったりする。
#端末ごとの調べ方(手元に調べたい端末がない時)
仮にNexus10でsoファイルを含むアプリを動かしたいとする。
- Nexus10のCPUを調べる。
⇒https://ja.wikipedia.org/wiki/Nexus_10
⇒ARMのCoretex-A15ベースのExynos 5250
2.Coretex-A15のアーキテクチャを調べる。
⇒https://ja.wikipedia.org/wiki/ARM%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
⇒v7-a
3.対応するABIを調べる。
⇒https://developer.android.com/ndk/guides/abis
⇒armeabi-v7a
なので、"armeabi-v7a"においたsoファイルが動いてることになる。
#端末ごとの調べ方(手元に調べたい端末がある時)
"adb shell"でつないで、"$ getprop | grep cpu"を叩くだけ。
[ro.product.cpu.abi]: [armeabi-v7a]
ABIが表示されすぐにわかる。
#サポートしているABIのsoファイル入れてないのになぜか動いてるけど。。。
ARMであれば、armeabi → armeabi-v7a → arm64-v8aの順に新しい。
基本的に下位互換性があるので、Nexus10であれば、armeabi-v7aにsoファイルがなくても、armeabiのsoファイルでアプリは動く。