Android资源管理中的SharedLibrary和Dynamic Reference-------之资源共享库(一)

一.引言

       共享库的概念,相信大家都有所了解,它有有许多优点。可以设想,在一个系统上要跑100个应用,并且它们都使用到了同一个库。如果这个库做成静态库,那么每个应用中都要打包一次这个库,100个应用就是100次,这无疑是重复的。我们可不可以在系统里只集成一次这个库呢,每个应用用到的时候再动态加载与链接,动态库的概念就这么产生了。现在,PC上Linux、Windows、Mac中动态库的应用已经非常广泛了。当然,Android中的动态库的应用也非常多,写JNI的同学都非常熟悉了。

       不过,我们今天讨论的动态库,指的并不是这些。我们知道一个APK中简单来说主要包括两部分:代码(DEX和so等)和资源(Asset、XML和Raw等)。前面我们 讲的动态库的概念主要是针对代码而言的,那么资源呢?我们可不可以动态加载和使用资源呢?答案当然是OK,毕竟现在已经有各种资源动态加载的框架了。但我们今天说的也不是这些框架,而是Android本身支不支持资源的动态加载呢?

二.framework-res.apk

      我们知道,Android本身也有很多资源,想必大家对这些代码都比较熟悉吧:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

</resources>

       没错,这就是我们新建一个Android Project的时候,IDE自动为我们生成的一个Theme。这个Theme就继承了Android本身的一个Theme:Theme.Material.Light.DarkActionBar。那么问题来了,Android的这个Theme是编译的时候IDE把它打包到我们的每一个APK里面去;还是说,这个Theme(当然也包括其它系统资源)只在系统中存在一份,我们的应用运行时,去系统加载呢?答案当然是后者,这是不是跟so库的动态加载有些类似了呢(补充,一般我们也会将so库打包到APK中,但如果系统中有对应的so库的时候,我们可以不用打包进去的)?

       其实,从应用的角度看,Android的framework包括两部分:java代码和资源。java代码比如我们用到的四大组件、各种控件等等,它们被打包成framework.jar,放在/system/framework/下面;资源则包括了系统的drawable、style、string等等,它们被打包成了framework-res.apk,也放在/system/framework/下面,前面说的Theme.Material.Light.DarkActionBar就存在于framework-res.apk。需要说明的是,别看framework-res.apk是一个APK,但它里面没有dex字节码,全部都是资源,完完全全的一个资源库。和so库的不同也就是它里面装的是资源,而so库里是本地机器码。当我们的应用起来后,在makeApplication的时候,就会去加载这个资源包,然后我们就可以使用Android提供的各种资源了。至于系统是怎么加载这个资源包的,我们后面会专门讨论,这里就不做详细介绍了。

三.ApplicationInfo.sharedLibraryFiles

        通过对系统的资源包framework-res.apk的分析,我们至少知道,Android中对资源是有着和共享库类似的加载机制的,但这种机制能不能拓展开来呢?设想一下,我们也可以做一个资源包,然后把它放到系统里面去,然后我们的各个应用不用每个都打包一次这些资源,大家共用这一套。

         当然,可以了,而且,Android也提供了支持,只是大家很少去关注罢了。OK,那么现在就让我们一起去扒一扒吧。ApplicationIfo这个类大家应该有用到吧,大家有没有注意到它内部的这些代码:

大家看着注释,能说出这些变量都是干什么用的吗?特别是

public String sourceDir;

public String[] resourceDirs;

public String[] sharedLibraryFiles;

public String nativeLibraryDir;

这四个变量。

 

public String sourceDir;//如果APK不分片的话,就是我们的APK在系统中的路径

public String[] resourceDirs;//这个是overlay Package的路径,可以有多个overlay package。overlay package的概念我们后面也会专门讨论。

public String nativeLibraryDir;;//这个就是我们的so库的路径了

        那么大家肯定会有疑问,public String[] sharedLibraryFiles;这个变量呢,sharedLibraryFiles应该也是共享库的路径吧。是的,这个是共享库的路径,但不是so库的路径。这里的共享库,指的就是我们前面所说的资源共享库。也就是说Android是支持资源共享库这个概念的。

四.uses-library

        Android Framework既然有了资源共享库(我们姑且这么叫吧)的机制,那么会不会顺手给应用层一个接口呢,这样多方便呀,而且也不用多大工作量,这个真的可以有^_^。

别说,这个还真的有。大家对AndroidManifest.xml都非常熟悉,它里面有许多标签,比如Application、Activity、Service等等,其中有一个标签叫做uses-library,就是来引入资源共享库的:

        这个是Android Framework中的一个project,路径为frameworks/base/tests/SharedLibrary/client/AndroidManifest.xml,我们看看其中的一个layout文件:

它分别引用了lib资源包里的string、style、drawable资源。当然,我们也可以换个姿势,在java文件里,通过R文件引用:

String[] animals = getResources().getStringArray(com.google.android.test.shared_library.R.array.animals);

这行妥妥的。

我们再来看一下被引用的库,其路径为frameworks/base/tests/SharedLibrary/lib/AndroidManifest.xml

<library android:name="com.google.android.test.shared_library" /> 这行声明 ”我是一个资源共享库“。

这个资源共享库APK和一般的APK有个区别,它的values目录下多了一个public.xml文件,并且这个public文件里的资源的包id是0x00而不是我们熟悉的0x7f(啰嗦一句,资源id的各个位的意义是:0xpptteeee,pp表示包id,占8位;tt表示type id,占8位;eeee表示entry id,占16位。package就不说了,type是指资源类型,比如drawable、color等;entry则表示资源的名称,这个后面介绍AssetManager的时候会详说):

做framework的同学应该非常清楚public.xml的作用,就是向别的应用export资源的。

另外,这个资源库的Android.mk也要注意,它和一般的应用不同,多了一个aapt flag: LOCAL_AAPT_FLAGS := --shared-lib

其实,也正是LOCAL_AAPT_FLAGS := --shared-lib,使得aapt在编译资源时,会给它的包id指定为0x00.

 

五.关于aar

       这种资源共享库的概念和aar相比,有何异同呢,我总结了一下:

       1. aar是资源的静态库,它里面的资源是打包到我们每一个应用里面去的,而资源共享库是一个独立的包,这是最本质的区别。

       2.aar里的资源是没有编译过的,所以它没有包名。假设我们的应用是com.demo.app,那么我们在java文件里引用aar里的资源可以用com.demo.app.R.xx.xxxx,在xml里引用aar的资源和引用自己应用的资源方式没有什么不同;但是资源共享库里的资源是编译过的,也是有包名的,因此它在java中和xml中的引用方式和我们对自己应用里的资源引用方式不太一样,如上面的图中。从这一点来说,确实aar用起来更方便。

       3.资源共享库是一个单独的包,需要安装或者放到特定目录或者需要特定的系统配置,aar则没有这个限制。这一点也是资源共享库大多用在手机厂商的系统应用中,而没能在App中广泛应用的最大原因。

       4.aar作为一种静态资源库,自然会出现不同应用重复集成的问题,这是所有静态库共同的的缺点,而资源共享库则没有这个 问题。

       5.aar库的依赖更强,库本身的集成、升级、维护比较麻烦。设想资源共享库自己更新一个版本,所有引用这个共享库的App无需任何改动就可以生效,活脱脱的热修复、模块化,哈哈,说得有些牵强了。但aar的更新就麻烦得多了,你要对所有使用这个aar的应用做修改、编译、打包、发布。

       现在,我们从应用层面介绍了Android的资源共享库的概念,大家对着代码看一下就会用了,非常简单,后面我们将从framework、aapt、AssetManager三个方面来介绍其实现原理,敬请期待

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值