【移动应用开发技术】在android里怎么部署so文件_第1页
【移动应用开发技术】在android里怎么部署so文件_第2页
【移动应用开发技术】在android里怎么部署so文件_第3页
【移动应用开发技术】在android里怎么部署so文件_第4页
【移动应用开发技术】在android里怎么部署so文件_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】在android里怎么部署so文件

今天在下给大家分享一下在android里怎么部署so文件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1.什么是CPU架构及ABIAndroid系统目前支持以下七种不同的CPU架构:ARMv***RMv7(从2010年起),x86(从2011年起),MIPS

(从2012年起),ARMv8,MIPS64和x86_64(从2014年起),每一种都关联着一个相应的ABI。应用程序二进制接口(ApplicationBinary

Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集、内存对齐到可用的系统函数库。在Android系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。2.为什么需要重点关注.so文件如果项目中使用到了NDK,它将会生成.so文件,因此显然你已经在关注它了。如果只是使用Java语言进行编码,你可能在想不需要关注.so文件了吧,因为Java是跨平台的。但事实上,即使你在项目中只是使用Java语言,很多情况下,你可能并没有意识到项目中依赖的函数库或者引擎库里面已经嵌入了.so文件,并依赖于不同的ABI。例如,项目中使用RenderScript支持库,OpenCV,Unity,android-gif-drawable,SQLCipher等,你都已经在生成的APK文件中包含.so文件了,而你需要关注.so文件。Android应用支持的ABI取决于APK中位于lib/ABI目录中的.so文件,其中ABI可能是上面说过的七种ABI中的一种。NativeLibs

Monitor这个应用可以帮助我们理解手机上安装的APK用到了哪些.so文件,以及.so文件来源于哪些函数库或者框架。当然,我们也可以自己对APP反编译来获取这些信息,不过相对麻烦一些。很多设备都支持多于一种的ABI,例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二进制包。但***是针对特定平台提供相应平台的二进制包,这种情况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而得到更好的性能(归功于最近的架构更新,例如硬件fpu,更多的寄存器,更好的向量化等)。我们可以通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。但你不应该从你的应用程序中读取它,因为Android包管理器安装APK时,会自动选择APK包中为对应系统ABI预编译好的.so文件,如果在对应的lib/ABI目录中存在.so文件的话。3..so文件应该放在什么地方我们往往很容易对.so文件应该放在或者生成到哪里感到困惑,下面是一个总结:Android

Studio工程放在main/jniLibs/ABI目录中(当然也可以通过在build.gradle文件中的设置jniLibs.srcDir属性自己指定)Eclipse工程放在libs/ABI目录中(这也是ndk-build命令默认生成.so文件的目录)AAR压缩包中位于jni/ABI目录中(.so文件会自动包含到引用AAR压缩包的APK中)最终APK文件中的lib/ABI目录中通过PackageManager安装后,在小于Android

5.0的系统中,.so文件位于app的nativeLibraryPath目录中;在大于等于Android

5.0的系统中,.so文件位于app的nativeLibraryRootDir/CPU_ARCH目录中。4.安装Apk时PackageManagerService选择解压so文件的策略在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压App的原生库目录,一般来说是放到/data/data/package-name/lib目录下,而根据系统和CPU架构的不同,其拷贝策略也是不一样的,不正确地配置so文件,比如某些App使用第三方的so时,只配置了其中某一种CPU架构的so,可能会造成App在某些机型上的适配问题。Android版本so拷贝策略策略问题5.配置so的建议针对Android系统的这些拷贝策略的问题,我们给出了一些配置so的建议:5.1针对armeabi和armeabi-v7a两种ABI方法1:由于armeabi-v7a指令集兼容armeabi指令集,所以如果损失一些应用的性能是可以接受的,同时不希望保留库的两份拷贝,可以移除armeabi-v7a目录和其下的库文件,只保留armeabi目录;比如Apk使用第三方的so只有armeabi这一种ABI时,可以考虑去掉Apk中lib目录下armeabi-v7a目录。方法2:在armeabi和armeabi-v7a目录下各放入一份so。5.2针对x86目前市面上的x86机型,为了兼容arm指令,基本都内置libhoudini模块,即二进制转码支持,该模块负责把ARM指令转换为x86指令,所以如果是出于Apk包大小的考虑,并且可以接受一些性能损失,可以选择删掉x86库目录,x86下配置的armeabi目录的so库一样可以正常加载使用。5.3针对64位ABI如果App开发者打算支持64位,那么64位的so要放全,否则可以选择不单独编译64位的so,全部使用32位的so,64位机型默认支持32位so的加载。比如Apk使用第三方的so只有32位ABI的so,可以考虑去掉Apk中lib目录下的64位ABI子目录,保证Apk安装后正常使用。5.AndroidStudio配置abiFiltersandroid

{

defaultConfig

{

ndk

{

abiFilters

'armeabi-v7a'

//,

'armeabi',

'arm64-v8a',

'x86',

'x86_64',

'mips',

'mips64'

}

}

}这句话的意思就是指定NDK需要兼容的架构,把除了armeabi-v7a以外的兼容包都过滤掉,只剩下一个armeabi-v7a的文件夹。即使我们没有指定其他的兼容框架,也需要一个过滤。当我们接入多个第三方库时,很可能第三方库做了多个平台的兼容。譬如fresco就做了各个平台的兼容,所以它创建了各个兼容平台的目录。因为只要出现了这个目录,系统就只会在这个目录里找.so文件而不会遍历其他的目录,所以就出现了找不到.so文件的情况。6.java.lang.UnsatisfiedLinkError该错误类型较多,以下进行分类:java.lang.UnsatisfiedLinkError

:

dlopen

failed:

library

//dlopen打开失败

java.lang.UnsatisfiedLinkError

:findLibrary

returned

null

//找不到library

java.lang.UnsatisfiedLinkError

:

Native

method

not

found

//找不到对应函数

java.lang.UnsatisfiedLinkError

:Cannot

load

library:

load_library

//无法load

library出现原因:显然出现上述崩溃的根本原因是:(1)so无法加载,可能是so不存在等原因(2)so正常加载,但是没有找到相应的函数针对第二个原因,显然相对来说很容易排查,而且在开发中,这样的函数调用必然会在编译时和debug模式下进行测试,所以这种原因产生的概率很小。那么下面主要总结几类“so无法加载”而导致上述崩溃的几种原因:6.1生成的so本身缺陷一个简单的例子:crash堆栈:java.lang.UnsatisfiedLinkError:

Cannot

load

library:

find_library(linker.cpp:889):

"/data/data/ease.nis.apptestunit/app_lib/libdemo.so"

failed

to

load

previously

at

java.lang.Runtime.load(Runtime.java:340)

at

java.lang.System.load(System.java:521)

at

ease.nis.bugrpt.ReLinker.loadLibrary(ReLinker.java:76)

at

com.example.crash.MainActivity.onCreate(MainActivity.java:272)

at

android.app.Activity.performCreate(Activity.java:5220)

at

android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1086)

at

android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2193)

at

android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2279)

at

android.app.ActivityThread.access$600(ActivityThread.java:142)

at

android.app.ActivityThread$H.handleMessage(ActivityThread.java:1272)

at

android.os.Handler.dispatchMessage(Handler.java:99)

at

android.os.Looper.loop(Looper.java:137)

at

android.app.ActivityThread.main(ActivityThread.java:5105)

at

java.lang.reflect.Method.invokeNative(Native

Method)

at

java.lang.reflect.Method.invoke(Method.java:511)

at

ernal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)

at

ernal.os.ZygoteInit.main(ZygoteInit.java:560)

at

dalvik.system.NativeStart.main(Native

Method)解决方法:查看原项目Application.mk,发现APP_STL:=

gnustl_shared。原方案使用的是共享库,这不一定都支持所有的机型,改用静态库gnustl_static问题解决。对应的在AndroidStudio中需要将共享库改用静态库gnustl_static。这一类关于so编译共享库问题,需要进行检查。APP_STL

可用值

system

系统默认

stlport_static

-

使用STLport作为静态库

stlport_shared

-

使用STLport

作为共享库

gnustl_static

-

使用GNU

libstdc++

作为静态库

gnustl_shared

-

使用GNU

libstdc++

作为共享库上述例子只是一个简单的例子,可能在so编译生成时,由于没有考虑共享库的机型匹配等原因导致UnsatisfiedLinkError崩溃,其次是64位32位系统架构问题,也可能导致UnsatisfiedLinkError崩溃。6.2手机设备没有空间在so正确生成情况下,会根据设置的支持so库框架生成对应的库。在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压到App的原生库目录,一般来说是放到/data/data/package-name/lib目录下,当准备加载native层的so时,虽然在Apk中有对应的so文件,但是由于手机设备没有足够的空间加载该so,导致加载失败,产生上述崩溃。6.3so配置错误倘若so正确生成,且手机空间充足,那么如上所述,在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压到App的原生库目录,一般来说是放到/data/data/package-name/lib目录下。但是根据系统和CPU架构的不同,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论