天天看點

Android一鍵多管道分發打包實戰和解析

當項目需要有更多的客戶的時候,你就會考慮将apk上架到應用商店了,無奈天朝Android應用商店真的是百家争鳴,據某地不完全統計已經有900+。若将Apk上架到所有的應用商店是個好主意,但是據統計也就那麼十來個應用商店的占有率已經超過95%了,是以我覺得并沒有必要上架所有應用商店。這裡就好比Android裡面适配機型一個道理,機型無數,但是也就那麼幾個品牌占有的絕大多數市場。

話說回來為什麼要打管道包(比如說應用寶要發一個apk,小米應用商店要發一個apk等等),而不是同一個apk放到每一個應用商店呢?主要有下列原因:

1. 不同的應用商店對于apk的要求不同,有的甚至需要一些定制,比如某些應用商店要求在啟動頁加入商店的Logo

2. 為了跟蹤每家應用商店的使用者數等等統計資料

幸運的是gradle天生就提供了打多管道包的功能,這裡我們主要解決下列問題:

  • 如何打多個管道的包
  • 如何支援友盟統計
  • 如何在代碼中根據不同管道做執行不同的代碼塊,即管道定制
  • 如何支援多包名打包
  • 一種對于BuildConfig的更有意思的用法(彩蛋)

修改build.gradle和預編譯BuildConfig類解析

在moudle的build.gradle的android元素下,有這麼productFlavors這麼一個函數,它支援不同“口味”的版本編譯。比如我們需要做一個應用寶的管道版本,可以添加下列代碼:

android {
    productFlavors {
        YingYongBao {
            manifestPlaceholders = [UMENG_CHANNEL:"YingYongBao"]
            buildConfigField "String", "CHANNEL", "\"YingYongBao\""
        }
}      

随後在AndroidManifest.xml的配置友盟管道号的地方改成:

<meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL}" />      

productFlavors中的manifestPlaceholder類似于給AndroidManifest檔案定義了一個變量,上述例子中改變量名字就加UMENT_CHANNEL,值為字元串YingYongBao,這樣子改管道打包出來的apk即可以釋出到應用寶市場上了。同時你在友盟的背景統計子產品控制台中,也可以看到一個叫做“YingYongBao”的管道來源,可以跟蹤該管道的使用者使用資料。這樣我們要解決的第2個問題OK了。

productFlavors中的buildConfigField是在等于在預編譯期間建立了一個變量叫做CHANNEL,類型是字元串類型,值是字元串“YingYongBao”。

當我們寫C/C++代碼的時候通常會寫預編譯宏變量,可以控制代碼中在不同編譯條件下的執行分支。比如:

#ifdef _MACRO_YING_YONG_BAO
{
// code for yingyongbao
}
#else
{
// code for others
}
#endif      

當需要執行應用寶那部分代碼的時候則編譯時打開宏_MACRO_YING_YONG_BAO。而Android Studio也提供了類似的機制,它在預編譯階段生成了一個叫做BuildConfig.java的類,它位于:

當我們預編譯時會自動生成這麼一個類,按照上述編譯應用寶管道的操作中,我們看下這個BuildConfig.java是什麼内容:

這裡發現有一個叫做CHANNEL的String常量,而且值是“YingYongBao”,是以想到那麼這裡為了讓不同管道執行不同的代碼,我們于是可以在代碼中這樣子寫:

if (BuildConfig.CHANNEL.equals("YingYongBao")) {
// code block for yingyongbao    
} else if (BuildConfig.CHANNEL.equals("360") {
// code block for 360
} else {
// default code
}      

這裡需要注意的一點,通過buildConfigField定義的變量中,如果是String類型的話,必須要在值裡面寫上轉義符号\",或者寫成:

buildConfigField "String", "CHANNEL", ‘"YingYongBao"’      

否則的話預編譯器會認為YingYongBao不是一個值而是另一個變量,進而報錯:

到此,第3個問題也解決了!

在Android Studio中一鍵打包

到現在還沒有說如何打包的事情,這點很簡單,隻要打開Android Studio的gradle面闆,重新整理task清單,會發現很多task,隻要輕按兩下下assembleRelease這個task即可。稍等一段時間,Android Studio自動幫你生成所有的管道的Apk。

生成的所有apk在這裡:

這裡有兩個注意點:

  1. 執行打包前,最好先執行下clean那個task
  2. build那個task也可以打所有管道的包,但是比較慢,因為它同時也打出來debug包,而assembleRelease隻打release包,理論上減少一半時間

問題1解決

多包名支援

在build.gradle中是用applicationId來表述包名的,在productFlavors中是可以嵌入applicationId的定義,比如我們在Beta這樣的管道中想要打出一個com.qianmi.xxx.beta的包名的apk,可以這麼寫:

productFlavors {
        Beta {
            manifestPlaceholders = [UMENG_CHANNEL:"Beta"]
            buildConfigField "String", "CHANNEL", "\"Beta\""
            applicationId "com.qianmi.xxx.beta"
        }

}      

問題4解決

BuildConfig的一種有意思的用法(彩蛋)

我們知道釋出出去的apk都是帶有簽名的,而從Android Studio等IDE中直接run到手機上的是沒有簽名的,但是兩個手機,一台裝了簽名的apk一台是直接run上去的,你能區分出來嗎(實際是看不出來的)?

如果我們能動态的區分出來,同時對于直接從IDE運作出來的Apk中在app的某個界面(比如關于界面)有下列标志多好?

而在正式釋出出來的版本中沒有“開發版本”這個字串。

首先我們在build.gradle中的android元素下的buildTypes函數中加入:

buildTypes {
        release {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources true
            signingConfig signingConfigs.release
            proguardFiles 'proguard-rules.pro'
        }

        debug {
            minifyEnabled false
            zipAlignEnabled true
            shrinkResources true
            buildConfigField "String", "CHANNEL", "\"dev\""
        }

    }      

這裡有一個release和一個debug。當你通過上述講解中的gradle task中打包時是release,打包時讀取具體的productFlavors。而如果你是直接從IDE運作出來調試的話,會檢查buildTypes中debug這個地方,這裡我們同樣把CHANNEL這個常量給定義出來了,值是dev。

于是我們再在關于界面,寫上下列語句即可:

if (BuildConfig.CHANNEL.equals("dev")) {
            tvVersion.setText("v" + AppUtils.getVersionName(getApplicationContext()) + " " + getString(R.string.dev_version));
        } else {
            tvVersion.setText("v" + AppUtils.getVersionName(getApplicationContext()));

        }      

題外話

到此為止,多管道打包問題已經解決。但是打包的時候發現如果管道越多實際上打包的時間是越慢的,因為Android Studio在為每個管道一個個的生成apk,是以我們這裡提供的方式僅僅适用于管道比較少的情況下。如果你真的想要在900個以上的應用市場釋出你們的apk,那麼顯然這種方式就不行了。這裡提供兩個解決方法。

一個是對同一個base的apk進行修改的方式,可以參考美團技術團隊的部落格:

http://tech.meituan.com/mt-apk-packaging.html

或者

http://blog.csdn.net/luck_apple/article/details/8634572?utm_source=tuicool&utm_medium=referral

第二個是試用一些廠商的支援多管道打包的軟體,比如360的加強寶:

http://jiagu.360.cn/

文末附上一家統計公司提供的國内應用市場占有率的報告:

轉載請注明出處: http://www.cnblogs.com/soaringEveryday/p/5368540.html

繼續閱讀