原始多渠道打包
原始多渠道打包的方式,指的是每次打包的時候在代碼中設置channelId,打包完這個渠道的apk包後,需要重新設置channelId再進行打包,如此反覆。該方式多出現在android早期的時候,多被一些剛入行的android工程師使用,或者是一些公司面對較少渠道的時候使用。
原理
原始多渠道打包就是個體力活,在較少渠道的時候可以使用,但是面對上千的渠道的時候,使用這種方式你會後悔當一名android開發工程師。它的原理是在應用代碼中設置渠道ID,使用的時候將渠道ID設置給數據分析接口,數據分析平臺通過該渠道ID分析之。其實後面多渠道方式的本質原理都是這樣的,但是具體擴展方式不同而已,將在後面的分析的時候介紹。
實現
- 第一步:設置渠道id
方式一 在代碼中直接設置channelId
- 1
- 1
方式二 在AndroidMainfest.xml中application中設置meta-data
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在代碼中獲取channelId
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
- 第二步:集成到sdk中,比如友盟sdk
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
優缺點
在渠道較少(個位數)的時候可以使用,但對於多渠道的時候太耗時耗力了。
友盟多渠道打包
該方法是友盟幾年前公佈的多渠道打包方式,並且在github開源了打包工具,友盟多渠道打包方式經歷了多次迭代,主要有兩種方式,一種是通過反編譯apk修改渠道信息,另一種是通過AXML解析器編輯修改渠道信息。
原理
-
第一種方法:
通過ApkTool進行解包,然後修改AndroidManifest中修改渠道標示,最後再通過ApkTool進行打包、簽名。 -
第二種方法:
使用AXML解析器axmleditor.jar,擁有很弱的編輯功能,工程中用來編輯二進制格式的 AndroidManifest.xml 文件.
實現
- 第一步 apktool解包apk
apktool是一個逆向工程工具,可以用它解碼(decode)並修改apk中的資源。接下來詳細介紹如何使用apktool生成渠道包。
在Android多渠道打包(一)介紹過,同樣需要在AndroidManifest.xml文件中定義元素,並在應用啓動的時候讀取清單文件中的渠道號。打包時,只需構建一次生成一個apk,然後在該apk的基礎上生成其他渠道包即可。
首先,使用apktool decode應用程序,在終端中輸入如下命令:
apktool d your_unsigned.apk build
解包後生成如下圖片的文件
- 第二步 使用python腳本修改AndroidManifest.xml中的渠道號
AndroidManifest.xml文件內容
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Python腳本
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
或者使用AXML解析器直接編輯修改AndroidManifest.xml中的渠道號
- 第三步 使用apktool重新構建未簽名的apk
apktool b build your_unsigned_apk
- 第四步 使用jarsigner重新簽名apk
jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore your_keystore_path -storepass your_storepass -signedjar your_signed_apk, your_unsigned_apk, your_alias
- 另在代碼中集成,比如友盟sdk
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
官方說明
- 最近更新
友盟本次更新最大的改變是放棄了 V2.x 版本中通過 Apktool 反編譯apk文件打包的方式,這種打包方式會對開發的apk文件做出大幅度的修改,可能會產生許多不兼容的問題,比如對jar包中包含資源的情況無法支持,對包含 .so 文件的apk兼容性也不好,而且在打包時 AndroidManifest.xml 文件中的特殊標籤會丟失。爲了解決這些問題減少對開發者apk文件的修改, 我們決定放棄這種方式,而採用直接編輯二進制的AndroidManifest.xml 文件的方式。這種方式只會修改 AndroidManifest.xml 文件,對於apk包中的資源文件和代碼文件都不會做任何改變。如果打包不成功,生成的apk文件有問題,在測試階段也可以快速發現,因爲修改只會影響AndroidManifest.xml 相關的少量的設置。
- 工具使用
axmleditor.jar 一個AXML解析器,擁有很弱的編輯功能,工程中用來編輯二進制格式的 AndroidManifest.xml 文件.
JarSigner.jar 給 Apk 簽名, SignApk.jar 文件是我們修改過的 apk 簽名工具,實現了和 ADT 中一樣的簽名方式.
這些Java工具都是使用java7編譯的,如果您還在使用Java 1.6
請留下issue。
DotNetZip 解壓縮和壓縮文件使用的是DotNetZip(Ionic.Zip.dll), 運行源碼需要加入這個庫.
優缺點
對比之前的老方法大大節省了構建時間,因爲該方法只需構建一次,然後通過腳本修改渠道並簽名就可。
但是對於三位數以上的渠道還是有點力不從心,另外該方法需要解壓縮、壓縮、重簽名耗費時間較多,重簽名可能會導致apk包在運行時有兼容性問題。
引用
maven&gradle打包
原理
都是採用在AndroidManifest.xml的節點中添加如下元素,構建時替換value值得方式。
實現
- Maven
Maven是一個軟件項目管理和自動構建工具,配合使用Android-maven-plugin插件,以及maven-resources-plugin插件可以很方便的生成渠道包,下面簡要介紹下打包過程,更多Maven以及插件的使用方法請參考相關文檔。
首先,在AndroidManifest.xml的節點中添加如下元素,用來定義渠道的來源:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
定義好渠道來源後,接下來就可以在程序啓動時讀取渠道號了:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
要替換AndroidManifest.xml文件定義的渠道號,還需要在pom.xml文件中配置Resources插件:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
準備工作已經完成,現在需要的就是實際的渠道號了。下面的腳本會遍歷渠道列表,逐個替換並打包:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在前期渠道很少時這種方法還可以接受,但只要渠道稍微增多該方法就不再適用了,原因是每打一個包都要執行一遍構建過程,效率太低。
- gradle
以友盟的渠道統計爲例,渠道信息一般在 AndroidManifest.xml中修改以下值:
- 1
- 2
- 3
- 1
- 2
- 3
首先你必須在AndroidManifest.xml中的meta-data修改以下的樣子:
- 1
- 2
- 3
- 1
- 2
- 3
其中${UMENG_CHANNEL_VALUE}
中的值就是你在gradle中自定義配置的值。
build.gradle文件就利用productFlavors這樣寫
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
其中[UMENG_CHANNEL_VALUE: "wandoujia"]
就是對應${UMENG_CHANNEL_VALUE}
的值。
不過現在有個更加簡潔的寫法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在android studio中sync gradle在build下可以看到
直接在gradle中點擊assemble
可構建所有渠道的包
單獨點擊對應渠道的assemble
比如assembleC360
可以單獨構建出C360渠道的包
代碼中獲取渠道值如下代碼
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
優缺點
maven&gradle對於每個渠道都會單獨構建一次,比較耗時,但是可以對各個渠道更加細化的定製
樣例參考:
Gradle多渠道打包
由於國內Android市場衆多渠道,爲了統計每個渠道的下載及其它數據統計,就需要我們針對每個渠道單獨打包,如果讓你打幾十個市場的包豈不煩死了,不過有了Gradle,這再也不是事了。 以友盟統計爲例,在AndroidManifest.xml裏面會有這麼一段:
<meta-data
android:name="UMENG_CHANNEL"
android:value="Channel_ID" />
裏面的Channel_ID就是渠道標示。我們的目標就是在編譯的時候這個值能夠自動變化。 * 第一步 在AndroidManifest.xml裏配置PlaceHolder
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
第二步 在build.gradle 設置productFlavors
android {
productFlavors {
xiaomi {}
_360 {}
baidu {}
wandoujia {}
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
然後直接執行 ./gradlew assembleRelease
然後就等待打包完成吧。
assemble 這個命令,會結合 Build Type 創建自己的task,如:
./gradlew assembleDebug
./gradlew assembleRelease
常用命令如下:(linux下是./gradlew,該腳本在項目下,windows直接gradlew即可)
./gradlew -v 版本號,首次運行,沒有gradle的要下載的哦。
./gradlew clean 刪除HelloWord/app目錄下的build文件夾
./gradlew build 檢查依賴並編譯打包
這裏注意的是 ./gradlew build 命令把debug、release環境的包都打出來,生成的包在目錄HelloWord/app/build/outputs/apk/下。如果正式發佈只需要打release的包,該怎麼辦呢,下面介紹一個很有用的命令 assemble, 如
./gradlew assembleDebug 編譯並打Debug包
./gradlew assemblexiaomiDebug 編譯並打xiaomi的debug包,其他類似
./gradlew assembleRelease 編譯並打Release的包
./gradlew assemblexiaomiRelease 編譯並打xiaomi的Release包,其他類似
./gradlew installRelease Release模式打包並安裝
./gradlew uninstallRelease 卸載Release模式包
http://www.jianshu.com/p/44d40f8e67c9 git自動獲取包名打包
360多渠道打包
來源
這個打包方法是由奇虎360的工程師開源出來的,這位大神在github的id是seven456
原理
利用的是Zip文件“可以添加comment(摘要)”的數據結構特點,在文件的末尾寫入任意數據,而不用重新解壓zip文件(apk文件就是zip文件格式);所以該工具不需要對apk文件解壓縮和重新簽名即可完成多渠道自動打包,高效速度快,無兼容性問題;
實現方式
- java源碼
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 使用方法
1、命令行使用說明:
用法:Java -jar MCPTool.jar [-path] [arg] [-contents] [arg] [-password] [arg]
-path APK文件路徑
-outdir 輸出路徑(可選),默認輸出到APK文件同一目錄
-contents 寫入內容集合,多個內容之間用“;”分割,如:googleplay;m360; 當沒有“-contents”參數時輸出已有文件中的content
-password 加密密鑰(可選),長度8位以上,如果沒有該參數,不加密
-version 顯示版本號
例如:
寫入:
java -jar MCPTool.jar -path D:/test.apk -outdir ./ -contents googleplay;m360; -password 12345678
讀取:
java -jar MCPTool.jar -path D:/test.apk -password 12345678
2、Android代碼中讀取寫入的渠道號:
導入MCPTool.jar中的MCPTool類,MCPTool.getChannelId(context, mcptoolPassword, defValue)讀出寫入的渠道號;
3、jenkins、hudson、ant使用說明:
請看MultiChannelPackageTool\build-ant\MCPTool\build.xml文件;
4、Windows下bat腳本運行說明:
拖拽文件即可完成多渠道打包:MultiChannelPackageTool\build-ant\MCPTool\MCPTool.bat;
拖拽文件檢查渠道號是否寫入成功:MultiChannelPackageTool\build-ant\MCPTool\MCPTool-check.bat;
- 獲取渠道號
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 1
優缺點
沒有解壓縮、壓縮、重簽名,沒有兼容性問題,速度最快;寫入的渠道號數據支持加密,安全可靠;
由於速度極快,我還可以作爲服務器端下載apk時動態寫入“特定數據”,用戶下載到apk後安裝啓動,讀取“特定數據”完成特定的操作;
如:加好友功能,下載前寫入用戶ID,用戶下載後啓動apk,讀取寫入的用戶ID,完成加好友操作,用戶體驗大大提升,沒有斷裂感;
當然,也可以寫入JSON數據,想做什麼就做什麼;
引用
seven456:MultiChannelPackageTool
360多渠道打包升級版:
原理
利用的是Zip文件“可以添加comment(摘要)”的數據結構特點,在文件的末尾寫入任意數據,而不用重新解壓zip文件(apk文件就是zip文件格式)。
實現
實現方式有三種:Python腳本、Java腳本、gradle構建
- 方法一:python腳本的方式
python源碼
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
python腳本
python PackerNg.py [file] [market] [output] [-h] [-s] [-t TEST]
方法二:java腳本的方式
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
java腳本
java -jar PackerNg.jar apkFile marketFile outputDir
方法三:gradle構建
在項目top level build.gradle中添加
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在 app level build.gradle中添加
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
着重幾點
- 改善了360多渠道打包方式中api兼容性的問題
ZipFile.getComment是ZIP文件註釋寫入,使用Java會導致APK文件被破壞,無法安裝。這裏是讀取ZIP文件註釋的問題,Java 7裏可以使用zipFile.getComment()方法直接讀取註釋,非常方便。但是Android系統直到API 19,也就是4.4以上的版本才支持 ZipFile.getComment() 方法。由於要兼容之前的版本,所以這個方法也不能使用。改爲:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- Android 7.0簽名校驗引起的安裝失敗
爲了提高Android系統的安全性,Google從Android 7.0開始增加一種新的增強簽名模式,從Android Gradle Plugin 2.2.0開始,構建系統在打包應用後簽名時默認使用APK signature scheme v2,該模式在原有的簽名模式上,增加校驗APK的SHA256哈希值,如果簽名後對APK作了任何修改,安裝時會校驗失敗,提示沒有簽名無法安裝,使用本工具修改的APK會無法安裝,解決辦法是在 signingConfigs 裏增加 v2SigningEnabled false ,禁用新版簽名模式,技術細節請看官方文檔:APK signature scheme v2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
優缺點
使用APK註釋保存渠道信息和MAGIC字節,從文件末尾讀取渠道信息,速度飛快
實現爲一個Gradle Plugin,支持定製輸出APK的文件名等信息,方便CI集成
提供Java版和Python的獨立命令行腳本,不依賴Gradle插件,支持獨立使用
缺點
沒有使用Android的productFlavors實現,無法利用flavors條件編譯的功能
總結
原始多渠道打包:
- 1
- 1
友盟多渠道打包:
- 1
- 2
- 3
- 1
- 2
- 3
360多渠道打包
- 1
- 2
- 3
- 1
- 2
- 3
360多渠道打包plus(進階版)
- 1
- 1
maven、gradle版
- 1
- 1
那麼我們選擇時可以按實際情況使用360多渠道打包plus,或者android studio gradle多渠道打包。需注意的是360多渠道打包plus無法通過android7.0簽名校驗,當然只要是通過後期修改apk文件的方式都不能通過android7.0的簽名校驗。