image

需求

在集成第三方的sdk时,某些时候第三方sdk会需要applicationID,举个栗子:

当我们集成 融云即时通讯 时,需要在Manifest中声明,如下所示:

    android:authorities="应用包名.FileProvider"    android:name="android.support.v4.content.FileProvider"    android:grantUriPermissions="true"    android:exported="false">    android:name="android.support.FILE_PROVIDER_PATHS"    android:resource="@xml/file_paths" />

没有进行组件化时,很简单,我们只需要在manifest中直接声明即可。

组件化之后 ,如果我们想在base module里面声明的话,是不行的,因为base module作为一个library是没有applicationId的。

解决思路

1、依然像以前那样写死

// Manifest.xml          // file_provider.xml<?xml version="1.0" encoding="utf-8"?>    com.xxx.fileprovider

这种方式试验了下,provoder是可以正常使用,但是融云没试验过,包名在base module里面写死了,感觉不舒服,难道我在其他项目compile了,还要回来改包名,不不不,拒绝拒绝。

2、覆盖思路,能不能在base module里面定义一个变量并在manifest里面使用,然后在app module里面定义个相同的变量,达到覆盖修改的目的。于是采用manifestPlaceholders(此思路来自stack overflow)

实现1

首先,在 base library的 build.gradle 中的defaultConfig{}里面设置manifestPlaceholders = [ PROVIDER_AUTH:""]

然后,在 base library的 manifest里面设置,

最后,在 App module 中的defaultConfig{}里面设置manifestPlaceholders = [ PROVIDER_AUTH: applicationId+".FileProvider"]

结果是不行,最终build出来的manifest里面的,authorities没有重新被赋值

更新自2018.10.10

后来使用极光推送sdk的时候发现,他也是使用manifestPlaceholders的方式来达成在Manifest中使用applicationId的,详细见下:
在编译好的manifest中会发现几个provider,例如:

然后极光文档要求我们在使用的时候要在我们的app build.gradle中这样使用:

manifestPlaceholders = [  JPUSH_PKGNAME: applicationId,  ...]

于是猜想,在极光的sdk中的manifest中,应该有如下代码:

于是我们可以依葫芦画瓢,在我们的base library的manifest中这样写:

     

然后在我们的业务module中这样写:

defaultConfig {  applicationId "com.xxx.yyy"  ...  manifestPlaceholders = [    PKG_NAME:applicationId  ]  ...}

这样我们就达成了在base module 的manifest中使用applicationId的目的啦,编译出来的业务module的manifest中,就会有

     

当然,这里还有个小问题,就是我们的base library会报错,说我们base library的manifest里面有个占位符PKG_NAME没有在build.gradle中声明,就和我们在使用极光sdk时,没有在业务module 的build.gradle中声明

manifestPlaceholders = [  JPUSH_PKGNAME: applicationId,  ...]

一样。

虽然我们依然可以提交到maven中,但是红红的,就是不舒服,于是我们可以在base library 的buildTypes的debug中声明一下PKG_NAME,如下:

buildTypes {        ...        debug{            manifestPlaceholders = [                    PKG_NAME:"",            ]        }        ...}

至此更新完结...

评论区说app module中的manifestPlaceholders不会影响base library的manifestPlaceholders,这里贴一下我的实验结果,可能每个人的做法有一点差异,导致结果不一样:

Base Library中的Manifest文件.png

Base Library中声明的manifestPlaceHolder变量.png Base Library编译后生成的manifest文件.png app module中声明的manifestPlaceHolder变量.png app module编译后生成的manifest文件.png

通过以上结果可以看出,app module中的manifestPlaceHolder是会覆盖掉base library中的manifestPlaceHolder的值。值得注意的是,我这里的base library是以 aar的形式 提供给app module依赖的,而不是以 project的形式 提供的。

实现2

在 base library的 manifest里面使用占位符,具体如下:

// base library的 manifest:

然后在 app module 的build.gradle里面修改base library的 manifest里的占位符的值,具体如下:

buildTypes {            android.applicationVariants.all { variant ->                variant.outputs.each { output ->                    output.processManifest.doLast{                        println variant.applicationId+".FileProvider"                        replaceInManifest(output, 'P_AUTHORITY', variant.applicationId+".FileProvider")                    }                }            }  }

这种方式试验了下,provider也是可以正常工作的,为了不在每个app module里面都重复写这段代码,我们可以将他放在common.gradle里面,用的时候compile就行啦,done.

如果各位大神有更好的实现方式,麻烦告知下,蟹蟹

更多相关文章

  1. Android(安卓)- Android(安卓)Studio 自动(auto)添加import 语句
  2. Android使用系统方法实现分享到QQ和微信!
  3. Android的线程使用来更新UI----Thread、Handler、Looper、TimerT
  4. Android(安卓)用axis2 webService产生java.lang.ClassCastExcept
  5. Android(安卓)SDK文档之Drawable Mutations
  6. 开始使用Android(安卓)Sutdio(三)创建一个Hello World程序
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. Android开发之使用Parcelable对自定义的
  2. IDA 调试SO
  3. 关于Android(安卓)Sensor的文章
  4. Android培训班(16)
  5. android anr分析方法
  6. android APK反编译及代码混淆
  7. android api code 学习之provider包
  8. Android(安卓)如何处理Search下的suggest
  9. Android(安卓)多媒体开发相关技巧
  10. Android开发——Android(安卓)Studio的ND