成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

渠道發(fā)行的Android多渠道打包實(shí)踐

移動(dòng)開發(fā) 新聞
由于各個(gè)渠道邏輯差異、底層依賴庫的沖突,對于ProxySDK的高內(nèi)聚和低耦合的設(shè)計(jì)要求還是比較高的。

01 前言

多渠道打包對于每一個(gè)Android開發(fā)來說應(yīng)該都不陌生,從最早的Eclipse上純手動(dòng)打包到Ant腳本打包,再到現(xiàn)在Android Studio的自帶的渠道配置,以及gradle腳本實(shí)現(xiàn)批量打包。多渠道打包的方案在不斷的優(yōu)化,打包速度也從原來的幾十個(gè)渠道包打一天到現(xiàn)在只需要幾小時(shí)。

但是上述方案只是替換了配置文件中的渠道信息,如果沒有源碼,只有一個(gè)apk文件,并且根據(jù)不同的渠道每個(gè)包里的模塊和代碼都要定制化,有沒有解決方案呢?

02 游戲渠道發(fā)行的打包

目前國內(nèi)安卓市場的渠道非常之多,其中有華為、小米、vivo、oppo等自帶操作系統(tǒng)或硬件設(shè)備的硬核廠商,基于自己移動(dòng)設(shè)備建立了非常大的用戶群體,還有應(yīng)用寶、九游等雖然沒有自己的移動(dòng)設(shè)備,但是憑借其app廣大的受眾,也積累了許多的用戶。對于要在這些渠道上發(fā)行游戲,就要接入這些渠道不同的sdk來實(shí)現(xiàn)渠道的登錄、支付等能力,并不像常規(guī)app那樣,只是改個(gè)channelId就好了。游戲?qū)τ趩蝹€(gè)渠道的接入可能就需要花上一周甚至更多時(shí)間,如果要同時(shí)接入幾十個(gè)渠道,對于游戲研發(fā)來說需要投入非常大的時(shí)間成本,另外上文所說的打包方案又該如何解決,一個(gè)游戲包打包往往需要幾小時(shí),如果每個(gè)渠道單獨(dú)打包,打完幾十個(gè)渠道包需要花上數(shù)十上百個(gè)小時(shí),再加上后期對于每個(gè)渠道sdk的迭代維護(hù),其中的成本可想而知。為此,我們需要提供給游戲研發(fā)一套能低成本的打包方案。

有別于傳統(tǒng)的app,自家研發(fā)的產(chǎn)品,在編譯過程中可以配置各種腳本實(shí)現(xiàn)多渠道打包。

在游戲渠道發(fā)行中,發(fā)行方并不是游戲的開發(fā)者(以下簡稱CP),因此我們只能拿到CP提供的apk(以下簡稱母包),我們需要基于母包來進(jìn)行各個(gè)渠道的定制整合,其中包括集成每個(gè)渠道不同的sdk以及他們的鑒權(quán)、登錄、支付等能力,最終打出各個(gè)渠道不同的渠道子包。

03 目標(biāo)規(guī)劃

針對上述的痛點(diǎn)我們不妨先定個(gè)小目標(biāo):游戲只接一個(gè)sdk,游戲只打一次包。

那么要完成這個(gè)“小目標(biāo)”我們就需要解決兩個(gè)問題:1、整合渠道,2、整合打包

3.1 整合渠道

這里的整合渠道并不是說把所有的渠道都接完放到一個(gè)大的sdk里,然后根據(jù)channelId來調(diào)用不同渠道的方法,這么做既不優(yōu)化也難以維護(hù)。所謂整合其實(shí)是通過一個(gè)統(tǒng)一的出口來對渠道進(jìn)行封裝,在我們常規(guī)的app開發(fā)中也有通過不同的flavor或者buildType動(dòng)態(tài)加載dependency的場景,那我們只要把每個(gè)渠道當(dāng)成一個(gè)單獨(dú)的module,不過由于我們是合作方,只能拿到游戲打完的apk包,我們不能把渠道當(dāng)成module集成在游戲的代碼里,只能變成單獨(dú)的apk去集成,在每個(gè)獨(dú)立的渠道apk里集成sdk的能力,再通過統(tǒng)一封裝的代理層來實(shí)現(xiàn)這些接口的對外暴露就行了,具體的架構(gòu)如下所示:

通過上圖可以看出整體的業(yè)務(wù)流程是:游戲調(diào)用proxy的代理接口→代理接口調(diào)用具體集成的渠道api,這樣無論底層的渠道如何變換,只要代理層的接口設(shè)計(jì)能覆蓋渠道所有的能力,那么對于上層游戲來說渠道的變化就是無感知的,這樣做到了游戲和渠道的徹底解耦,也做到了渠道的整合。

3.2 整合打包

游戲打一次包往往需要幾個(gè)小時(shí),如果每個(gè)渠道打一次包,耗時(shí)巨大,但是如果按照上文架構(gòu)設(shè)計(jì),游戲只要接入一次代理sdk,然后我們只要在打渠道包的時(shí)候替換渠道模塊的代碼以及資源就行了。

04 技術(shù)實(shí)現(xiàn)

既然目標(biāo)已經(jīng)確定,那么我們就需要具體的打包方案來實(shí)現(xiàn)。

傳統(tǒng)的渠道打包方式無法滿足,游戲發(fā)行需要有一套獨(dú)特的多渠道打包方式。

整理一下需求:我們有一個(gè)apk,還有一份渠道sdk的代碼,我們需要把這些代碼合并到apk中生成一個(gè)新的apk,這個(gè)流程聽著是不是很熟悉?這不就是反編譯和回編譯的過程嗎。

谷歌官方的apktool提供了反編譯,回編譯等能力,基于它我們可以設(shè)計(jì)出大致流程:

整個(gè)流程中大部分的工作調(diào)用apktool的api就能夠?qū)崿F(xiàn),但是如何去替換注入渠道sdk的代碼呢?

熟悉逆向的同學(xué)一定知道,apktool反編譯之后生成的是smali文件,大概長成下面這樣:

別說修改了,這種類似匯編的代碼的可讀性都很差。

換一種思路,如果我們編輯的是java文件,那是不是就方便很多了。

順著這種思路,如果我們有一個(gè)集成了渠道sdk的demo.apk,再提供給CP一個(gè)代理sdk,通過apktool反編譯demo.apk之后生成的smali文件替換母包反編譯后對應(yīng)的代理類,這樣就可以實(shí)現(xiàn)渠道代碼的注入了。

同樣,我們只要針對每個(gè)渠道單獨(dú)開發(fā)一個(gè)接入的demo.apk就可以復(fù)用在所有的游戲上。這樣既做到了渠道的獨(dú)立,又可以橫向擴(kuò)展。

因此,我們設(shè)計(jì)了一套代理層,對上暴露登錄,支付,鑒權(quán)等基礎(chǔ)能力的api,內(nèi)部是渠道api的調(diào)用,基于這套代碼打包出來的就是demo.apk了。

其次,渠道之間還有很多差異化的內(nèi)容要處理,最簡單就是同一個(gè)游戲不同的渠道包名是不一樣的。

這里就要用到反編譯之后的yml文件了,這個(gè)文件記錄了反編譯的配置信息,用于回編譯的時(shí)候讀取,用修改包名舉例,只要增加第一行的配置就可以改變回編譯之后的包名了。

同時(shí),yml文件還可以自定義很多配置,這里就不展開了,感興趣的同學(xué)可以自行了解一下。

最后,解決了代碼合并,渠道差異化的配置之后,整個(gè)打包過程大致為以下幾步:

1. 準(zhǔn)備游戲母包和對應(yīng)的渠道demo.apk

2. 通過apktool d xxx命令分別反編譯這兩個(gè)apk,得到如下文件結(jié)構(gòu)

3. 合并AndroidManifest.xml,合并assets中的文件,合并lib,合并并替換res中的相應(yīng)資源和配置文件,替換smali中的相關(guān)文件

4. 通過apktool b xxx命令回編譯apk

5. 通過簽名工具對回編譯的apk進(jìn)行簽名

4.1 腳本打包

雖然打包步驟就簡單的五步,但是其中步驟3的資源整合和替換是非常繁瑣的。

AndroidManifest合并:

1. 使用xml解析器,獲取所有的節(jié)點(diǎn)

2. 合并相同節(jié)點(diǎn)

3. 添加渠道特殊邏輯

4. 添加游戲特殊邏輯

5. 替換包名相關(guān)的節(jié)點(diǎn)(provider,permission等)

6. 創(chuàng)建新的manifest

assets合并:

1. 合并assets文件夾

2. 添加渠道特殊邏輯

3. Splash資源替換

4. 生成新的assets文件夾

lib合并:

1. 獲取母包libs

2. 獲取渠道libs,并且和母包libs進(jìn)行對比

3. 合并相同的libs

4. 根據(jù)游戲支持的cpu復(fù)制對應(yīng)的libs

5. 生成新的libs文件夾

res合并:

res比較特殊,它的合并需要拆成兩個(gè)部分:一個(gè)是anim,color,drawable,layout等文件夾的合并,另外是values的合并;

除values外其他文件的合并類似assets合并,替換相同的文件,合并其他文件,生成新的文件夾;

values文件夾的合并就要逐條解析文件內(nèi)容進(jìn)行合并;

最后還是要加上渠道的特殊邏輯,生成新的res文件夾。

smali合并:

首先找到對應(yīng)的代理層文件夾,把demo.apk的文件替換到母包中對應(yīng)位置;

需要注意的是很多渠道的sdk比較大,方法數(shù)可能會(huì)超65535的限制,合并的時(shí)候我們通過腳本統(tǒng)計(jì)每個(gè)smali文件夾里類的方法數(shù),當(dāng)方法數(shù)累加超過閾值之后會(huì)新建smali_classes2文件夾,把后續(xù)類遷移到后面的文件夾中。

這些操作如果單純靠人工手動(dòng)處理不僅非常耗時(shí),而且還容易出錯(cuò)。我們整理完合并替換規(guī)則之后,實(shí)現(xiàn)了一個(gè)打包工具來幫我們處理這些繁瑣的工作。

以下是資源替換的工具類:

至此,我們就可以把繁瑣的人工打包過程轉(zhuǎn)換成簡單的腳本命令來實(shí)現(xiàn),節(jié)省時(shí)間的同時(shí)還能保證準(zhǔn)確率。

4.2 工具打包

雖然腳本打包已經(jīng)非常便捷了,但其實(shí)由于每位同學(xué)的電腦環(huán)境不同,同一份腳本在不同的電腦上運(yùn)行的結(jié)果也會(huì)有差異,環(huán)境差異的報(bào)錯(cuò)對打包也會(huì)有一定程度的影響,因此,我們需要一個(gè)相對統(tǒng)一穩(wěn)定的環(huán)境來執(zhí)行打包任務(wù),這就可以使用傳統(tǒng)的持續(xù)集成工具:jenkins

于是我們基于打包腳本和jenkins,部署了一套高可用的游戲渠道發(fā)行打包工具,降低了打包的門檻和費(fèi)力度,讓打包效率有了進(jìn)一步的提升。

4.3 平臺(tái)打包

腳本也好,jenkins也好,其實(shí)都是比較偏向于開發(fā)的工具,然而打包不僅僅是開發(fā)用,更重要的是打完包之后交付給測試以及業(yè)務(wù)方,那么如果有一個(gè)非開發(fā)也能使用的,更直觀、更低門檻、更產(chǎn)品化的方案,是否能在工作流提效上有更好的幫助,為此我們還設(shè)計(jì)、研發(fā)UO打包平臺(tái),致力于讓業(yè)務(wù)同學(xué)也能夠輕松的打出渠道包。

05 避坑建議

其實(shí)整個(gè)研發(fā)工程并不像上文所說的一帆風(fēng)順,其中也遇到了許多奇怪問題,以下挑幾個(gè)典型的與各位分享:

5.1 合并游戲母包和渠道demo

是遇到單dex方法數(shù)超 出64K問題

部分渠道的sdk自帶了很多的方法,此時(shí)合并成一個(gè)dex文件時(shí),可能出現(xiàn)方法數(shù)超出65536的問題。其實(shí)方法數(shù)超的問題相信很多安卓研發(fā)都遇到過,現(xiàn)在只需要配置multiDexEnable true就可以在編譯的時(shí)候自動(dòng)分dex打包,但是對于游戲來說,我們拿到的是已經(jīng)編譯后的apk,因此沒有編譯工具會(huì)替我們進(jìn)行dex1、dex2分包,我們需要通過配置來模擬編譯工具的分包邏輯,實(shí)行手動(dòng)分包。

5.2 加固對出包流程的影響

部分游戲接入了加固平臺(tái),這會(huì)導(dǎo)致合并好母包和渠道demo.apk之后,生成的游戲渠道包啟動(dòng)閃退。遇到這種情況,我們需要改變一下出包流程。

流程由原來的:

加固后母包 -> 生成未簽名的渠道包 -> 簽名 -> 得到渠道包,但是啟動(dòng)會(huì)閃退

將加固動(dòng)作往后移動(dòng),改為:

未加固母包 -> 生成未簽名的渠道包 -> 加固 -> 簽名 -> 得到可用的渠道包

5.3 資源文件

由于二次打包aapt會(huì)重新生成R.smali文件,會(huì)產(chǎn)生兩個(gè)問題:

1. R文件的路徑產(chǎn)生變化:

由于每個(gè)渠道的游戲包名都不同,最終渠道包的R文件路徑也不同,如果游戲中直接通過R.id.xxx的方式調(diào)用,這里的R引用的是游戲原有的包名,R文件本質(zhì)是一個(gè)類,如果路徑發(fā)生了變化,那么我們代碼中對R文件的引用就會(huì)找不到類,解決這個(gè)問題可以有兩個(gè)思路,修改所有R文件引用,改成新的包名,或者在老的包名路徑下復(fù)制一份R文件。

大部分游戲的native代碼并不多,其中極少部分游戲會(huì)通過R.id.xxx的方式獲取資源,對于這種游戲我們在合并smali文件的時(shí)候,會(huì)根據(jù)配置來判斷是否要在游戲原來的包名路徑下保留R文件。

同時(shí),為了防止游戲的R文件id發(fā)生變化,我們會(huì)在新包名的目錄下復(fù)制一份游戲的R文件,確保游戲的資源id不發(fā)生變化。

對于我們sdk自己的id,為了防止sdk的資源id和游戲沖突,我們sdk的資源id就交給aapt重新生成,因此,我們sdk內(nèi)部不能通過R.id.xxx的方式來獲取資源id,我們調(diào)用Context.getResources().getIdentifier()這個(gè)方法,通過包名+資源名的方式來獲取到資源id,避免了二次打包之后id改變造成的crash。

同樣,雖然大部分渠道sdk里面也調(diào)用了getIdentifier來獲取資源id,但是也有個(gè)別渠道直接使用了R.id.xxx的方式來獲取,對于這種情況,在二次打包后由于上述id改變的原因,會(huì)導(dǎo)致crash。

對于這種問題其實(shí)和游戲的R文件一樣,只要保證原始包名下有對應(yīng)的R文件來避免引用錯(cuò)誤就可以解決了。

2. 資源id變化:

由于新增了資源,資源id會(huì)變化,同時(shí)母包和demo包里都會(huì)有一些公用的基礎(chǔ)組件,同一個(gè)資源的id在兩個(gè)包中可能是不一樣的。

大家都知道,打完包之后會(huì)生成resource.arsc文件,這個(gè)文件是資源索引文件,解包之后apktool會(huì)根據(jù)resource.arsc文件生成public.xml,這個(gè)文件里面保存了資源id的值,那么我們要統(tǒng)一id就需要用public.xml中的值覆蓋demo里面原有的值,大致流程如下:

我們通過解析game和sdk的public.xml文件,然后用sdk里的資源和game進(jìn)行對比:

1. 如果sdk內(nèi)的資源game里沒有,把資源保存到新增資源集合A中

2. 如果sdk中有g(shù)ame里一樣的資源,我們會(huì)保留game里的id,并且記錄sdk的新舊id映射保存到集合B中

3. 合并的時(shí)候會(huì)先去讀集合A中的id,判斷是否有沖突,如果和現(xiàn)有id沖突了,會(huì)通過一定的規(guī)則重新生成id,并且也和步驟2一樣,把新舊id的映射保存到集合B中

4. 讀取集合B,全量搜索舊id的值,替換成新id

5. 生成新的public.xml

大致方法如上所示,一些細(xì)節(jié)的實(shí)現(xiàn)就不占用篇幅贅述了,至此,資源文件相關(guān)的處理就完成了。

5.4 provider、permission

作為android四大組件的ContentProvider大家一定不會(huì)陌生,在使用的時(shí)候需要在manifest中聲明,如下:

其中authorities是唯一標(biāo)識(shí),渠道sdk中ContentProvider的authorities都會(huì)使用包名+類名的方式來聲明

這樣對于集成了渠道sdk的demo.apk來說,所有ContentProvider的authorities都是相同的,這就會(huì)導(dǎo)致如果單渠道多個(gè)游戲,當(dāng)?shù)诙€(gè)游戲安裝的時(shí)候就會(huì)由于authorities沖突導(dǎo)致失敗,因此我們首先需要用特殊的占位符替換包名字段,然后再manifest合并的時(shí)候識(shí)別占位符,用渠道子包的包名來替換。

當(dāng)然,如果這么簡單就能處理完,就不會(huì)出現(xiàn)在”避坑建議“里了,其實(shí)很多渠道的ContentProvider聲明是放在自己sdk的manifest里的,對于這樣的渠道,我們需要在集成渠道sdk工程里的manifest進(jìn)行authorities替換,需要使用replace,這樣在渠道demo打包的時(shí)候,manifest合并過程中就會(huì)把渠道sdk內(nèi)部的authorities改成我們自定義的authorities。

最后,同樣的問題還會(huì)出現(xiàn)在permission中,有一些渠道sdk中聲明了自定義的permission來限制對自己服務(wù)或者是組件的調(diào)用,處理這部分問題的方法和provider類似,這里就不贅述了。

06 優(yōu)化對比

6.1 流程優(yōu)化

整個(gè)打包平臺(tái)的方案,解決了之前出包流程上耗時(shí)的點(diǎn):

1. 包體多次傳輸

打包平臺(tái)將原來的上傳→下載→上傳的三次傳輸過程簡化成了單次上傳。

2. 人工響應(yīng)時(shí)間

工作時(shí)間響應(yīng)時(shí)間是比較穩(wěn)定的,但是當(dāng)出現(xiàn)突發(fā)情況,很有可能會(huì)有非工作時(shí)間(午夜、假日)的打包需求,這時(shí)候可能由于各種原因技術(shù)無法及時(shí)出包,通過平臺(tái)出包可以避免此類的響應(yīng)問題。

3. 加固流程

現(xiàn)在加固基本是每個(gè)app必備的流程,有一部分游戲加固是在簽名前對每一個(gè)渠道包進(jìn)行一次加固,然而目前我們加固是采用第三方的解決方案,基于這種情況就會(huì)中斷我們的打包流程,在簽名前還需要給第三方進(jìn)行一次加固,然后再簽名,并且這樣也會(huì)造成多次的游戲包上傳下載的操作,嚴(yán)重影響出包效率,也增加了很多人工操作的工作量。

為了進(jìn)一步提升打包體驗(yàn)和效率,我們整合了部分加固方案,讓加固變成了打包流程的一個(gè)部分,流程對比如下:

從上圖可以看到通過平臺(tái)集成了加固流程后,每個(gè)包額外又減少了6次傳輸,以及一系列的人工操作,對于打包的時(shí)間和體驗(yàn)有非常大的提升。

6.2 耗時(shí)對比

游戲包不同于別的app,單個(gè)游戲都在1-2G不等,單次傳輸?shù)暮臅r(shí)也在3-5分鐘,如果是外網(wǎng)環(huán)境速度會(huì)更慢,優(yōu)化了兩次傳輸流程后,整體出包流程提升6-10分鐘/個(gè)包,平均每個(gè)游戲接入的渠道有8-10家,相當(dāng)于每次出包縮短了一個(gè)小時(shí)的耗時(shí)。

對于加固包而言,平時(shí)整個(gè)流程可能需要1-2個(gè)小時(shí),中間由于上傳、加固等多方響應(yīng)時(shí)間,可能會(huì)更長,但是通過系統(tǒng)只需要十幾分鐘就能完成所有渠道的出包。

我們用重生細(xì)胞做了一次測試,8個(gè)渠道整個(gè)打包、加固、簽名一共只用了20分鐘都不到,其中耗時(shí)的還是加固流程,可以看到下面無需加固的bangGream 7個(gè)渠道只用了3分鐘。

07 總結(jié)

本文看似簡單的過程,其實(shí)由于各個(gè)渠道邏輯差異、底層依賴庫的沖突,對于ProxySDK的高內(nèi)聚和低耦合的設(shè)計(jì)要求還是比較高的,開發(fā)過程中也經(jīng)過了幾次改版和踩坑,最終才交了一份階段性的答卷。

其次apktool的本身的問題也給我們造成了不少麻煩,經(jīng)過不同版本的嘗試,以及各種配置修改、試錯(cuò)之后才確定了一個(gè)符合我們需求的穩(wěn)定版本。

未來我們還會(huì)往平臺(tái)化的方向探索,追求推出一款高可用的游戲多渠道打包平臺(tái)。

責(zé)任編輯:張燕妮 來源: 嗶哩嗶哩技術(shù)
相關(guān)推薦

2016-12-14 15:13:30

GradleAndroid定制化打包

2019-05-21 14:22:28

Android渠道統(tǒng)計(jì)打包

2009-10-20 11:22:10

Linux備份方式

2017-02-15 12:59:23

Android渠道打包技術(shù)小結(jié)

2009-08-24 15:24:34

IT運(yùn)維管理ITIL運(yùn)維流程摩卡軟件

2022-02-23 16:56:43

Python多渠道歸因模型數(shù)據(jù)驅(qū)動(dòng)

2014-07-07 17:13:49

SAP華為

2012-05-24 14:26:25

CNZZ統(tǒng)計(jì)移動(dòng)開發(fā)

2023-04-07 07:31:17

渠道數(shù)據(jù)

2012-01-09 14:17:44

Android應(yīng)用商店

2013-04-23 13:23:56

Aspect聯(lián)絡(luò)中心呼叫中心

2016-01-06 10:30:02

渠道云供應(yīng)商云應(yīng)用

2011-07-15 11:17:18

寶通英特爾服務(wù)器

2012-05-09 16:46:47

2012-05-10 09:06:26

2012-04-26 22:51:23

Android

2011-11-21 12:40:38

移動(dòng)應(yīng)用推廣

2011-11-25 10:27:15

2022-05-12 16:28:42

數(shù)據(jù)

2017-04-28 10:46:50

營銷
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美激情国产日韩精品一区18 | 精品国产精品国产偷麻豆 | 最新91在线| 精品一区二区三区免费视频 | 99爱在线 | 国产高清av免费观看 | 亚洲精品久久久一区二区三区 | 在线免费黄色小视频 | 性高湖久久久久久久久3小时 | 福利视频网 | 伊人一区| 福利电影在线 | 91一区二区三区在线观看 | 久草在线 | 亚洲精品久久久一区二区三区 | 国产精品一区二区在线播放 | 国产在线精品一区二区 | 中文字幕欧美日韩 | 欧洲精品在线观看 | 精品国产一区二区三区久久 | 精品久久久久久国产 | 一区二区国产精品 | 精品一二三区在线观看 | 日韩福利片 | 色狠狠桃花综合 | 欧美日韩一区二区三区四区 | 免费在线观看一区二区 | 一区二视频 | 看羞羞视频免费 | 婷婷色在线播放 | 男人的天堂久久 | 精品欧美乱码久久久久久1区2区 | 亚洲欧美成人在线 | 精品九九| 亚洲国产精品一区二区三区 | 国产在线一区二区三区 | 国产成人精品免费视频大全最热 | 国产日日操 | 亚洲国产精品视频 | 免费高清成人 | 亚洲中午字幕 |