如果你是把so放在libs/armeabi/下,eclipse中so會自動打包進去,然后使用System.load("data/data/xxx.xxx.xxx/lib/xx.so");載入so。
如果你放到assert下的話,程序運行后將assert中的so寫到data/data/xxx.xxx.xxx/files/下。然后使用System.load("data/data/xxx.xxx.xxx/files/xx.so")加載。
Android應用中使用到C代碼,編譯成so文件打包進apk的libs路徑下。因為要支持ARMv5和ARMv7,libs下有armeabi和armeabi-v7a兩個目錄。安全的做法是編譯庫C代碼時,Application.mk中打開,
APP_ABI := armeabi armeabi-v7a
編譯生成的兩份so文件各自放到項目工程的armeabi/armeabi-v7a目錄中。有時還需要針對v7a平台編譯支持NEON和不支持NEON的庫。譬如這個例子,
in armeabi/: libp.so, libd.so, libvh.so, libvn.so in armeabi-v7a/: libp.so, libd.so, libd_neon.so, libvh.so, libvn.so
需要注意這一點:The 'armeabi-v7a' machine code will not run on ARMv5 or ARMv6 based devices. 如果損失一些應用的性能是可以接受的,不希望保留庫的兩份拷貝,可以移除armeabi-v7a目錄和其下的庫文件,只保留armeabi目錄。在安裝應用時,行為是這樣的,
When installing an application, the package manager service will scan the .apk and look for any shared library of the form:
lib/<primary-abi>/lib<name>.so
If one is found, then it is copied under $APPDIR/lib/lib.so, where $APPDIR corresponds to the application's specific data directory.
If none is found, and a secondary ABI is defined, the service will then scan for shared libraries of the form:lib/<secondary-abi>/lib<name>.so
If anything is found, then it is copied under $APPDIR/lib/lib.so.
什么是primary abi和secondary abi呢,
The Android system knows at runtime which ABI(s) it supports. More precisely, up to two build-specific system properties are used to indicate:
the 'primary' ABI for the device, corresponding to the machine code used in the system image itself.
an optional 'secondary' ABI, corresponding to another ABI that is also supported by the system image.
For example, a typical ARMv5TE-based device would only define the primary ABI as 'armeabi' and not define a secondary one.
On the other hand, a typical ARMv7-based device would define the primary ABI to 'armeabi-v7a' and the secondary one to 'armeabi' since it can run application native binaries generated for both of them.
This mechanism ensures that the best machine code for the target device is automatically extracted from the package at installation time.
考慮這樣一個情況,在打包apk時,armeabi-v7a目錄下放了所需的部分so文件。還是上面那個例子,
in armeabi/: libp.so, libd.so, libvh.so, libvn.so in armeabi-v7a/: libd.so, libd_neon.so
如此,安裝運行在v7a的設備上,會發生什么? 嘗試了一些手機和平板,CPU都是ARMv7的,Android都是4.x的。行為是拷貝以下庫文件到$APPDIR/lib/目錄下,
armeabi-v7a/libd.so, armeabi-v7a/libd_neon.so, armeabi/libp.so, armeabi/libvh.so, armeabi/libvn.so
符合特殊需求,libd對性能影響較大,針對ARMv7設備,使用armeabi-v7a的庫,其他都使用armeabi的庫。
但是遇到在一台ARMv7+Android2.3.4的手機上,加載libp.so報錯。
再嘗試另一台ARMv7+Android2.3.5的手機,一樣的現象。
針對這兩台手機,如果打包apk時移除armeabi-v7a目錄,不會報錯。
難道Android2.3的設備,package manager service的行為有異?