需求
在集成第三方的sdk時,某些時候第三方sdk會需要applicationID,舉個栗子:
當我們集成 融云即時通訊 時距贷,需要在Manifest中聲明,如下所示:
android:authorities="應(yīng)用包名.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
<provider
android:authorities="@string/fileprovider"
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
// file_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="fileprovider">com.xxx.fileprovider</string>
</resources>
這種方式試驗了下姜盈,provoder是可以正常使用,但是融云沒試驗過配阵,包名在base module里面寫死了馏颂,感覺不舒服,難道我在其他項目compile了棋傍,還要回來改包名救拉,不不不,拒絕拒絕瘫拣。
2亿絮、覆蓋思路,能不能在base module里面定義一個變量并在manifest里面使用拂铡,然后在app module里面定義個相同的變量壹无,達到覆蓋修改的目的。于是采用manifestPlaceholders(此思路來自stack overflow)
實現(xiàn)1
首先感帅,在 base library的 build.gradle 中的defaultConfig{}
里面設(shè)置manifestPlaceholders = [ PROVIDER_AUTH:""]
斗锭,
然后,在 base library的 manifest里面設(shè)置<provider android:authorities="${PROVIDER_AUTH}"></provider>
,
最后失球,在 App module 中的defaultConfig{}
里面設(shè)置manifestPlaceholders = [ PROVIDER_AUTH: applicationId+".FileProvider"]
結(jié)果是不行岖是,最終build出來的manifest里面的<provider android:authorities=""></provider>
,authorities沒有重新被賦值
更新自2018.10.10
后來使用極光推送sdk的時候發(fā)現(xiàn)实苞,他也是使用manifestPlaceholders的方式來達成在Manifest中使用applicationId的豺撑,詳細見下:
在編譯好的manifest中會發(fā)現(xiàn)幾個provider,例如:
<provider
android:name="cn.jpush.android.service.DataProvider"
android:authorities="com.xxx.yyy.DataProvider"
android:exported="false" />
然后極光文檔要求我們在使用的時候要在我們的app build.gradle中這樣使用:
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
...
]
于是猜想黔牵,在極光的sdk中的manifest中聪轿,應(yīng)該有如下代碼:
<provider
android:name="cn.jpush.android.service.DataProvider"
android:authorities="${JPUSH_PKGNAME}.DataProvider"
android:exported="false" />
于是我們可以依葫蘆畫瓢,在我們的base library的manifest中這樣寫:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${PKG_NAME}.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
然后在我們的業(yè)務(wù)module中這樣寫:
defaultConfig {
applicationId "com.xxx.yyy"
...
manifestPlaceholders = [
PKG_NAME:applicationId
]
...
}
這樣我們就達成了在base module 的manifest中使用applicationId的目的啦猾浦,編譯出來的業(yè)務(wù)module的manifest中陆错,就會有
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.xxx.yyy.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
當然,這里還有個小問題金赦,就是我們的base library會報錯音瓷,說我們base library的manifest里面有個占位符PKG_NAME沒有在build.gradle中聲明,就和我們在使用極光sdk時夹抗,沒有在業(yè)務(wù)module 的build.gradle中聲明
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
...
]
一樣绳慎。
雖然我們依然可以提交到maven中,但是紅紅的,就是不舒服杏愤,于是我們可以在base library 的buildTypes的debug中聲明一下PKG_NAME靡砌,如下:
buildTypes {
...
debug{
manifestPlaceholders = [
PKG_NAME:"",
]
}
...
}
至此更新完結(jié)...
評論區(qū)說app module中的manifestPlaceholders不會影響base library的manifestPlaceholders
,這里貼一下我的實驗結(jié)果珊楼,可能每個人的做法有一點差異乏奥,導致結(jié)果不一樣:
通過以上結(jié)果可以看出,app module中的manifestPlaceHolder是會覆蓋掉base library中的manifestPlaceHolder的值亥曹。值得注意的是邓了,我這里的base library是以 aar的形式 提供給app module依賴的,而不是以 project的形式 提供的媳瞪。
實現(xiàn)2
在 base library的 manifest里面使用占位符骗炉,具體如下:
// base library的 manifest:
<provider android:authorities="P_AUTHORITY"></provider>
然后在 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.
如果各位大神有更好的實現(xiàn)方式,麻煩告知下把将,蟹蟹??