日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android】多渠道打包与签名机制

發布時間:2024/3/12 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android】多渠道打包与签名机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【Android】多渠道打包與簽名機制

多渠道打包

我們在發布APP時,往往需要生成多個渠道包,以上傳到不同的應用市場。

而每個渠道包中,都可以包含各自的渠道信息,當APP和后臺交互或進行數據上報時,就可以帶上各自的渠道信息,通過這種方式,我們就能統計到每個分發市場的下載數,用戶數等關鍵信息。

多渠道打包的方式

ProductFlavor

作為Android開發人,我們肯定知道,Android默認為我們提供了這樣的一個Gradle插件庫:

classpath "com.android.tools.build:gradle:4.0.1"

然后我們會在module中的build.gradle中引入具體的插件,比如:

apply plugin: 'com.android.application'

而ProductFlavor,則是這個插件中的一個配置,或者說是這個插件提供的一個API。

那么怎么使用ProductFlavor進行多渠道打包呢?

其實很簡單,我們只需要在module中的build.gradle中,寫如下代碼

apply plugin: 'com.android.application' android {// ...flavorDimensions "default"file("channel.txt").readLines().each { channel ->// 基于channel,使用productFlavors.create方法,創建一個productFlavor(變種)productFlavors.create(channel, {dimension "default"// 填充AndroidManifest中的my_channel的值manifestPlaceholders = [my_channel: channel]})} } // ...

上面的代碼是groovy代碼,我來解釋一下它的大致意思:

1、首先使用了相對路徑,找到與build.gradle的同一級目錄下的channel.txt文件

2、讀取channel.txt文件中的每一行內容,并用channel變量表示

3、基于channel變量,使用productFlavors.create方法,創建一個productFlavor(也叫做變種)

4、對于每個變種的AndroidManifest,填充AndroidManifest中的my_channel的值

為了填充AndroidManifest中的my_channel的值,我們還需要在AndroidManifest.xml中寫如下代碼:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.ycx.demo"><application// ...<meta-dataandroid:name="CHANNEL_VALUE"android:value="${my_channel}" /></application></manifest>

這樣,每次在構建app的時候,就會將AndroidManifest中的my_channel替換成對應變種的channel值。

而channel.txt文件,我們可以這樣寫:

通過以上操作,我們app就具備生成多渠道包的能力了,我們點擊AS的Build Variants按鈕,就會看到如下變種信息:

可見,有6個變種可選。但是channel.txt文件明明只寫了 3 個,為什么是 6 個變種呢?

那是因為默認情況下,我們一個App默認就會包含兩個變種,分別是DebugRelease

所以我們使用productFlavors.create創建了 N 個變種,那么我們應用實際上將會有N * 2個變種(N個Debug變種 + N個Release變種)

使用渠道信息

既然已經可以打包多個渠道包了,那么我們下面就來使用各個渠道的渠道信息吧!

當我們選中xiaomiDebug這個變種進行打包,那么打包出來的APK中的AndroidManifest.xml會是這樣的:

可見,它生成了一個渠道信息,即xiaomi。

既然在AndroidManifest.xml已經可以拿到渠道信息,那么在java代碼中拿到渠道信息也就輕而易舉了。

有了這個渠道信息,我們就可以將這個信息上報給業務后臺,從而就能統計到每個應用市場的下載數等關鍵信息了。

如何優化多渠道打包

使用官方提供的ProductFlavor進行多渠道打包,其實是相當耗時的,因為對于每一個渠道包,都需要進行一次完整的APK打包過程,如果一次打包耗時5分鐘,那么100個包將需要500分鐘,這就有點夸張了。

那么有沒有更好的多渠道打包方案呢?

那是肯定的。美團的Wall,騰信的VasDolly等插件都是不錯的選擇。

而這些插件的都不需要在打包時將所有渠道包都完整的打包一次,它們的大致原理是往APK中的簽名文件夾中添加一個記錄渠道信息的文件,從而將渠道信息注入到apk中(V1簽名)。

而如果我們想要修改APK中的文件,我們就必須防止破壞APK的簽名,一旦我們破壞了APK的簽名,APK將無法安裝。

所以優化多渠道打包耗時,就轉變為如下問題:

如何在不破壞APK簽名的前提下,往APK中注入渠道信息?

在講多渠道的優化之前,我們就需要先對Android的簽名機制有一個深入的理解。

Android的簽名機制

Android為什么需要簽名 ?

如果了解 HTTPS 的通信流程,應該知道,在消息通信時,必須解決兩個問題:

  • 確保消息來源的真實性
  • 確保消息不會被第三方篡改

而在安裝 APK 時,同樣需要確保 APK 來源的真實性,以及 APK 沒有被第三方篡改。

想要了解Android中是如何實現簽名的,就需要了解幾個概念:消息摘要、數字簽名和數字證書。

消息摘要

消息摘要就是在消息數據上,執行一個單向的 Hash 函數,生成一個固定長度的 Hash 值,這個Hash值即是消息摘要。

消息摘要有如下的特性,無論輸入的消息數據有多長,計算出來的消息摘要的長度總是固定的,另外,消息摘要函數是單向函數,也就是說只能進行正向的信息摘要,無法從摘要中恢復出任何的消息。一般情況下,不會出現兩條消息,它們對應的消息摘要相同。

正是由于消息摘要的以上特性,使得消息摘要算法被廣泛應用在數字簽名領域

常見的消息摘要算法有 MD5 算法、 SHA-1、SHA-256等。目前 Android 簽名使用的默認算法就是 SHA-256 。

注意,消息摘要只能保證消息的完整性,并不能保證消息的不可篡改性。

那么,怎么保證消息的不可篡改性呢?

這就是得說到另一個概念了 —— 數字簽名。

在講數字簽名之前,我們需要再簡單的了解幾個相關概念:公鑰密碼體制、對稱加密算法、非對稱加密算法。

公鑰密碼體制

公鑰密碼體制分為三個部分,公鑰、私鑰、加密解密算法,它的加密解密過程如下:

  • 加密:通過加密算法和公鑰對明文進行加密,得到密文
  • 解密:通過解密算法和私鑰對密文進行解密,得到明文

也就是說,公鑰加密的內容,只能由私鑰進行解密,如果不知道私鑰,密文是無法被解密的。

在實際的使用中,有需要的人會生成一對公鑰和私鑰,把公鑰發布出去給別人使用,自己保留私鑰。

對稱加密算法

在對稱加密算法中,加密和解密都是使用的同一個密鑰。

因此對稱加密算法要保證安全性的話,密鑰要做好保密,只能讓使用的人知道,不能對外公開。

非對稱加密算法

在非對稱加密算法中,加密使用的密鑰和解密使用的密鑰是不相同的。

數字簽名

當使用私鑰進行加密,使用公鑰進行解密時,這個過程就稱為簽名

它和加密有什么區別呢?

因為公鑰是公開的,所以任何持有公鑰的人都能解密私鑰加密過的密文,所以這個過程并不能保證消息的安全性,但是它卻能保證消息來源的準確性和不可否認性

也就是說,如果使用公鑰能正常解密某一個密文,那么就能證明這段密文一定是由私鑰持有者發布的,而不是其他第三方發布的,并且私鑰持有者不能否認他曾經發布過該消息。故此將該過程稱為簽名。

常規的簽名方案應該是摘要算法和數字簽名和加密算法結合起來使用的,它的過程是這樣的:

  • 用摘要算法對數據進行摘要,得到摘要值
  • 再把摘要值用信源的私鑰加密

通過以上兩步得到的消息就是原始信息的數字簽名。

綜上所述,數字簽名其實就是非對稱加密技術 + 消息摘要技術的結合。

數字證書

通過數字簽名技術,可以解決可靠通信的問題。

但是大家有沒有注意到,前面講的數字簽名方法,有一個前提,就是消息的接收者必須事先得到正確的公鑰。

如果一開始公鑰就被別篡改了,那么這個公鑰解密出來的數據將不會是信源發送的數據。

那么如何保證公鑰的安全可信呢?這就要靠數字證書來解決了。

數字證書是一個經證書授權中心數字簽名的包含公鑰擁有者信息以及公鑰的文件,它包含以下內容:

  • 證書發布機構
  • 證書有效期
  • 證書所有人的公鑰
  • 證書所有人的名稱
  • 證書使用的簽名算法
  • 證書發行者對證書的數字簽名

可以看出,數字證書本身也用到了數字簽名技術,只不過簽名的內容是整個證書。

與普通數字簽名不同的是,數字證書的簽名者不是隨隨便便一個普通機構,而是 CA 機構。

一般來說,這些 CA 機構的根證書已經在設備出廠前預先安裝到了你的設備上了。

所以,數字證書可以保證證書里的公鑰確實是這個證書所有者的,或者證書可以用來確認對方的身份。

可見,數字證書主要是用來解決公鑰的安全發放問題。

Android的簽名機制

如果我們熟悉apk打包流程,我們肯定知道,在打包流程的倒數第二步,會對apk進行簽名,Android中對apk進行簽名工具有兩種:jarsigner和 apksigner,它們的簽名算法沒什么區別,主要是簽名使用的文件不同。

  • jarsigner:jdk自帶的簽名工具,可對 jar 進行簽名,使用 keystore 文件進行簽名,生成的簽名文件默認使用 keystore 的別名命名
  • apksignersdk:專門用于Android應用的簽名工具。生成的簽名文件統一使用CERT命名。

簽名校驗的過程

Android為我們提供了三個簽名版本,分別是V1、V2、V3,其中,V2簽名僅支持Android 7.0及之后版本,V3簽名支持Android 9.0及以上版本。

如果是在Android 9.0以上的系統安裝一個apk,會先判斷apk是否使用V3簽名,如果沒有使用V3簽名,就判斷是否使用了V2簽名,如果還是沒有使用V2簽名,則確定apk是用了V1簽名,那么這時就會使用V1簽名的來校驗,如果校驗失敗就拒絕安裝,如果校驗成功則安裝。

這是Android官方提供的一個apk校驗簽名的流程圖:

由此可見,一個apk是可以同時使用三個版本的簽名的,如果同時使用三個版本的簽名方式,則優先使用V3的簽名進行校驗。

需要注意的是,對于覆蓋安裝的情況,簽名校驗只支持升級,而不支持降級。也就是說設備上安裝了一個使用 V1 簽名的 APK,可以使用 V2 簽名的 APK 進行覆蓋安裝,反之則是不允許的 。

而在Android studio中,我們可以選擇打包V2和V1簽名,但是目前AS并不支持V3簽名,

如果我們想使用V3簽名的話,可以自己通過命令行的方式來自行操作apksigner工具進行V3簽名,具體就不舉例了。

V1簽名機制

如果我們在apk中使用了V1簽名,我們會發現, 在apk中,會多出一個META-INF文件夾,而META-INF文件夾中會有三個子文件:

  • MANIFEST.MF
  • CERT.SF
  • CERT.RSA

這三個文件就是V1簽名的產物,下面我對它們進行簡單的介紹。

1、MANIFEST.MF:對apk中每個文件都使用SHA-256算法提取出該文件的的消息摘要然后進行base64編碼,得到的編碼值作為SHA1-Digest屬性的值寫入到 MANIFEST.MF 文件中的一個塊中,且每一個塊都有一個Name屬性, 其值就是該文件在 APK 包中的路徑,如下所示:

2、CERT.SF:對apk中每個文件以及MANIFEST.MF文件都使用SHA-256算法提取出每個文件的的消息摘要然后進行base64編碼,可以理解為SF文件其實是用于保護MANIFEST.MF文件的。

3、CERT.RSA:這里會把 CERT.SF 文件,用私鑰計算出簽名,然后將簽名以及包含公鑰信息的數字證書一同寫入 CERT.RSA 中保存。

其實說白了,就是MANIFEST.MF文件是用于保護apk中所有的文件的,而CERT.S文件則是用于保護MANIFEST.MF文件,CERT.RSA用于保護 CERT.SF 文件,這樣一環扣一環,來保證apk的安全性。

注意,

V1簽名保護的是apk中已存在的文件不被修改

也就是說,如果把apk解壓后,再添加一個自己的文件,然后再壓縮成apk,那么這個apk仍然是可以安裝成功的,因為我們新添加的那個文件本身就不在V1簽名的保護范圍內。

那么,如果我們添加的這個文件是一個渠道信息相關的文件,那是不是就做到了在不破壞APK簽名的前提下,往APK中注入渠道信息了。

V2簽名機制

其實,我們可以發現, V1 簽名有兩個地方可以改進:

  • 簽名校驗速度慢:校驗過程中需要對apk中所有文件進行摘要計算,在 APK 資源很多、性能較差的機器上簽名校驗會花費較長時間,導致安裝速度慢
  • 完整性保障不夠:META-INF 目錄用來存放簽名,所以該目錄本身是不計入簽名校驗過程的

為了解決這兩個問題,在 Android 7.0 版本中,引入了V2簽名。

V1簽名保護的ZIP中已存在的文件,而V2簽名保護的則是整個APK的字節數據

當apk中加入一個文件,那個這個apk對應的字節數據就會發生變化了,所以V2簽名就不能像V1簽名那樣往apk中的META-INF文件夾注入一個新文件從而進行多渠道打包了。

那么在V2簽名下,如何在不破壞APK簽名的前提下,往APK中注入渠道信息呢?

首先我們要知道,其實apk就是一個zip格式的壓縮包,因此,apk的數據格式就跟zip格式的壓縮包一樣了。

按照ZIP文件格式,插入一個簽名分塊區域,記錄簽名信息。

在簽名前,ZIP的數據格式分三塊,分別是藍、綠、紫這三塊,而簽名后,在藍和綠之間插入了一個簽名分塊: APK Signing Block,如下圖所示:

那么,這個簽名分塊的數據格式是怎么的呢?

在整個簽名塊中,第一個size of block數據塊,它占8個字節,記錄的是除自己本身之外的整個簽名塊的長度。

再看藍色部分,這里記錄的是id-value的鍵值對,這里就是用來記錄渠道信息的地方了。在里的鍵值對中,有一個id為0x7109871a,它所對應的value,就是V2簽名的簽名數據。

當所有的鍵值對記錄完后,還有一個size of block數據塊,它同樣占8各個字節,它記錄的也是除自己本身之外的整個簽名塊的長度。

最后,有個magic數據塊,也叫做魔數,它占16個字節,它是用于標記文件格式的,

有的人會問:文件的后綴名不是也能標記文件格式嗎?

其實,文件的后綴名的本質是為了讓程序更方便的識別文件的格式,從而選擇不同的處理方式來處理這個文件。

但是也會有人手動去修改一個文件的后綴名的情況,比如一個jpg格式的文件,手動將其后綴修改為.png,這種操作并不能從根源上修改文件的類型,換句話說,即使手動修改為.png文件,它本質上仍是一個.jpg文件。

而真正用來標記文件格式的,是魔數。

V2簽名下如何優化多渠道打包?

根據官網的描述,V2簽名保護的內容是藍、綠、紫這三塊區域,以及第二部分(簽名分塊)中的 id為0x7109871a的數據,而對于簽名分塊的其他數據,是不會保證的。

所以當我們往簽名分塊中插入一個id-value鍵值對,來記錄渠道信息,是不會破壞apk的簽名的。

按照這個思路,就能在V2簽名下,在不破壞APK簽名的前提下,往APK中注入渠道信息了。

注入渠道信息流程如下:

1、解析apk,判斷是否使用了V2簽名,如果是則定位到V2對應的簽名分塊區域

2、在簽名分塊中添加包含渠道信息的 id-value鍵值對

3、拷貝原apk,并修改簽名分塊數據,生成帶有渠道信息的apk

V3簽名機制

V3簽名其實跟V2簽名很相似,它仍然采用檢查整個壓縮包的校驗方式,

不同的是在 V2 簽名后插入的簽名塊中,又添加了一個Attr塊,在這個新塊中,會記錄我們之前的簽名信息以及新的簽名信息,

以密鑰轉輪的方案,來做簽名的替換和升級。這意味著,只要舊簽名證書在手,我們就可以通過它在新的 APK 文件中,更改簽名。

由此可知,V3簽名下優化多渠道打包的方案和V2簽名是一樣的。

總結

以上是生活随笔為你收集整理的【Android】多渠道打包与签名机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。