API環境切換需求
需求背景
鑒于app在打包debug ,release, dev 等環境的時候,請求后天api接口的服務器地址不一樣.導致測試可能頻繁的問你要不同環境的測試apk包.
當工程大到一定程度的時候,gradle打包特別的慢.即使你自己有優化過,而且測試嫌麻煩,開發也覺得麻煩.
實現思路
api地址變化的應該就基地址,全部變化也有辦法處理.這里把基地址用一個 public static 的 String Url 變量去裝載.
1:默認 Url 地址使用release的地址.
2:release版本的apk 按照需求,啟動app調轉到splash界面.debug版本的apk 跳轉到api選擇界面,當選擇好api環境后,在調轉到原splash界面.
3:選擇api環境的時候,去修改 這個被public static 修飾的Url
實現策略
1:修改被public static 修飾的String 不是問題.
2:根據不同apk版本啟動不同的界面.這個是一個問題,之前沒處理過類似的需求.好在google 有提供一種解決思路 餃子 manifest merge (合并多個清單文件),就是根據這個合并算法去解決這個問題.
實現細節
第一步
創建debug文件夾,新建的項目一般會有3個文件夾,一個是默認類型,一個test 類型,一個Android test類型,這里我們在創建一個debug類型的.
xml文件合并可以合并java 文件,和 資源文件.
我們這里定要創建manifest文件,這是算法配置的核心,配置就是在這里設置的,其次還有資源文件.
注意創建的時候文件格式應該和main類型的保持一致,可以將as切換到android模式下檢查.
我們這里添加了一個EnvChangeActivity 和對應的布局文件.
第二步:合并要合并的文件
這里我們想修改啟動的界面為EnvChangeActivity.所以我們要替換點原main類型下的manifest文件中的配置.
如上設置就會把原Mainactivity中的配置全部替換成當前manifest文件中的配置.后面我們在解釋這些配置.這里將EnvChangeActivity設置成了啟動界面.所以完成了修改啟動界面的功能.
第三步
創建一個java配置文件
可以不創在main類型下面.
在EnvChangeActivity中修改地址就好了.修改完之后在跳轉到MainActivity.就原邏輯保持一致了
到這里需求的就已經說明完了.
合并
接下來就說明合并的算法,在我們使用gradle編譯打包的時候,合并工具會自動幫我們合并.
合并工具根據每個清單文件的優先級將所有清單文件按順序合并到一個文件中。 例如,如果您有 3 個清單文件,則會先將優先級最低的清單合并到優先級第 2 高的清單中,然后再將合并后的清單合并到優先級最高的清單中
1清單文件構建變體如果您的變體有多個源集,則其清單優先級如下:
構建變體清單(如 src/demoDebug/)
構建類型清單(如 src/debug/)
產品定制清單(如 src/demo/)如果您使用的是定制維度,清單優先級將與每個維度在 flavorDimensions
屬性中的列示順序(按優先級由高到低的順序排列)對應。
2應用模塊的主清單文件
3所包括庫中的清單文件如果您有多個庫,則其清單優先級與依賴順序(庫出現在 Gradle dependencies
塊中的順序)匹配。
合并沖突啟發式算法
合并工具可以在邏輯上將一個清單中的每個 XML 元素與另一個清單中的對應元素相匹配。
如果優先級較低的清單中的元素與優先級較高的清單中的任何元素均不匹配,則該元素將被添加至合并清單。 但是,如果有匹配元素,則合并工具會嘗試將其中的所有屬性合并到相同元素中。如果工具發現兩個清單包含相同屬性,但值不相同,則會出現合并沖突。
但是,在某些情況下,合并工具會采取其他行為方式以避免合并沖突:
<manifest>
元素中的屬性絕不合并—僅使用優先級最高的清單中的屬性。
android:required 屬性 <uses-feature>and <uses-library>
元素使用 OR 合并,因此如果出現沖突,系統將應用 "true"
并始終包括某個清單所需的功能或庫。<uses-sdk>元素始終使用優先級較高的清單中的值,但以下情況除外:如果低優先級清單的 minSdkVersion 值較高,除非您應用 overrideLibrary合并規則。
如果低優先級清單的 targetSdkVersion 值較低,合并工具將使用高優先級清單中的值,但也會添加任何必要的系統權限,以確保所導入的庫繼續正常工作(適用于較高的 Android 版本具有更多權限限制的情況)。
絕不會在清單之間匹配 <intent-filter>
元素。 每個元素都被視為唯一元素,并添加至合并清單中的常用父元素。
合并規則標記
合并規則標記是一個 XML 屬性,可用于表達您對關于如何解決合并沖突或刪除不需要的元素和屬性的首選項。 您可以對整個元素或只對元素中的特定屬性應用標記。
合并兩個清單文件時,合并工具會在高優先級清單文件中尋找這些標記。
所有標記均屬于 Android tools 命名空間,因此您必須先在 <manifest> 元素中聲明此命名空間,如下文所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp"
xmlns:tools="http://schemas.android.com/tools">
節點標記
要向整個 XML 元素(給定清單元素中的所有元素及其所有子標記)應用合并規則,請使用以下屬性:
tools:node="merge"
如果使用合并沖突啟發式算法時沒有沖突,則合并此標記中的所有屬性以及所有嵌套元素。這是元素的默認行為。
低優先級清單
<activity android:name=”com.example.ActivityOne”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
高優先級清單
activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
tools:node="merge”>
</activity>
合并結果
<activity android:name=”com.example.ActivityOne”
android:screenOrientation=”portrait”
android:windowSoftInputMode=”stateUnchanged”>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
tools:node="remove"
低優先級清單
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
android:value=”@string/moo”/>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>
高優先級清單
<activity-alias android:name=”com.example.alias”>
<meta-data tools:node=”removeAll”/>
</activity-alias>```
合并結果
<activity-alias android:name=”com.example.alias”>
</activity-alias>
tools:node="replace"
完全替換低優先級元素。 也就是說,如果低優先級清單中有匹配元素,請將其忽略并完全按照其在此清單中顯示樣子來使用該元素。
低優先級清單
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”cow”
android:value=”@string/moo”/>
<meta-data android:name=”duck”
android:value=”@string/quack”/>
</activity-alias>```
高優先級清單
<activity-alias android:name=”com.example.alias”
tools:node=”replace”>
<meta-data android:name=”fox”
android:value=”@string/dingeringeding”/>
</activity-alias>
合并結果
<activity-alias android:name=”com.example.alias”>
<meta-data android:name=”fox”
android:value=”@string/dingeringeding”/>
</activity-alias>