Android多渠道打包(定制化馬甲包)

1、為什么要進行多渠道打包?

安卓應用商店(一個商店也叫做一個渠道,如豌豆莢,360手機助手,應用寶)眾多,大大小小幾百個,每當我們發新版本時,需要將Android客戶端分發到各個應用市場,為了統計這些市場的效果(下載量、活躍數等),需要有一種方法來唯一標識它們,所以才有了多渠道打包。

2、如何統計各個渠道的下載量、活躍數?

現在有比較成熟的第三方應用幫我們實現統計功能(比如友盟),統計的本質就是收集用戶信息傳輸到后臺,后臺生成報表,幫助我們跟蹤分析并完善app。通過android系統的方法已經可以獲取到引用版本號,版本名稱,系統版本,機型等各種信息,唯獨應用商店(渠道)的信息我們是沒有辦法從系統獲取到的,所以我們就人為的在apk里面添加渠道信息(其實就用一個字段進行標識,如wandoujia360yingyongbao),我們只要把這些信息打包到apk文件并將信息傳輸到后臺,后臺根據這個標識,可以統計各個渠道的下載量了。
多渠道打包只需要關注兩件事情:

    1. 將渠道信息寫入apk文件
    1. 將apk中的渠道信息傳輸到統計后臺

3、使用Gradle進行多渠道批量打包**

  1. 通常都是在在AndroidManifest.xml中加入渠道區分標識寫入一個meta標簽:

    <meta-data   
       android:name="channel"    
       android:value="${channel}" 
    />
    
  2. 在app目錄下在build.gradle中配置productFlavors添加如下代碼:

    productFlavors {
        qihu360 {} // 360手機助手
        yingyongbao {} // 騰訊應用寶
        wandoujia {} // 豌豆莢
        baidu {} // 百度手機助手
        miui {} // 小米
        flyme {} // 魅族
        lenovo {} // 聯想-樂商店
        oppo {} // Oppo-可可軟件商店
        huawei {} // 華為
        vivo {} // vivo
        hiapk {} // 安卓市場
        sj91 {} // 91手機助手
        sogou {} // 搜狗手機市場
        sohu {} // 搜狐應用中心
        taobao {} // 淘寶手機助手
        gfan {} // 機鋒
        appchina {} // 應用匯
        mumayi {} // 木螞蟻
        wangyi163 {} // 網易應用
        nduoa {} // N多市場
        mm10086 {} // MM商城-中國移動
        wostore {} // WO商店
        youyi {} // 優異
        uc {} // UC+開發平臺
        anzhi {} // 安智市場
        google {} // google play
        amazon {} // 亞馬遜
    }
    productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [channel: name]
    }
    

    AndroidStudio的Build -> Generate signed apk打簽名包時即可選擇設置渠道:

    Paste_Image.png

  3. 在代碼中獲取渠道信息:

public static String getFlavorChannel(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            return appInfo.metaData.getString("channel");
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        return "";
    }
  1. 在android studio中測試不同渠道的apk。
Paste_Image.png

4.APP定制渠道包(馬甲包)

在App的開發過程中,經常會遇到產品或者運營的同事提出要制作馬甲包的需求;馬甲包簡單來說就是原APP的小號,與原APP包除了包名,應用名稱、圖標等給用戶加以區分的東西,其他功能基本不變亦或者只采用原App的部分功能的APP包。

  1. ApplicationId,版本號
    Android 應用都有自己的包名。包名是設備上每個應用程序的唯一標識,同樣也是在各個下載平臺的唯一標識。就是說,假如你已經使用某個包名來發布應用,就不能再去改變應用的包名,因為這樣做會導致你的應用被視為一個全新的應用,你現有的用戶也不會收到應用的更新通知。
    隨著渠道越來越多,不同渠道對應用的要求也不盡相同。有時候我們需要發布不同的版本,例如 prohd 版本,支持用戶可以下載安裝不同的版本。那么我們需要設置不同的ApplicationId和對應的版本號, 同時要與 PackageName 解耦合。
  • 代碼中引用的 R 類要保持不變;
  • 在構建不同版本的應用時,對應的(引用了 R 的) .java 源文件也不能改動。

那么我們只需要在productFlavors對應的渠道中指定applicationIdversionCodeversionName,例我們指定GooglePlayapplicationId:

 productFlavors {
        GooglePlay {
            //指定這個渠道的版本號
            versionCode 2
            versionName "1.2"
            //指定區別于其他渠道的 applicationId
            applicationId "com.liujc.androidtools.hd"
        } 
        yingyongbao {} // 騰訊應用寶
        wandoujia {} // 豌豆莢
        baidu {} // 百度手機助手
        miui {} // 小米
        //其他...
    }
  1. BuildConfig
    Gradle會在generateSources階段為flavor生成一個BuildConfig.java文件。BuildConfig類默認提供了一些常量字段,比如應用的版本名(VERSION_NAME),應用的包名(PACKAGE_NAME)等。更強大的是,開發者還可以添加自定義的一些字段。下面的示例假設debug版開啟LOG功能,使用debug的api,而release版則使用不開啟LOG和使用release時的api:
    buildTypes {
        debug {
            // debug模式下,顯示log
            buildConfigField("boolean", "LOG_DEBUG", "true")
            buildConfigField ("String", "API_HOST", "\"http://api.test.com\"")//debug API Host
        }
        release {
            // release模式下,不顯示log
            buildConfigField("boolean", "LOG_DEBUG", "false")
            buildConfigField("String", "API_HOST", "\"http://api.release.com\"")//release API Host
        }
    }
    
    那么代碼中就可以使用 BuildConfig.LOG_DEBUG 和 BuildConfig.API_HOST 了。
    備注: 這里簡單介紹下buildConfigField 方法,可以發現其有三個參數:
    /**
     * Adds a new field to the generated BuildConfig class.
     *
     * <p>The field is generated as: {@code <type> <name> = <value>;}
     *
     * <p>This means each of these must have valid Java content. If the type is a String, then the
     * value should include quotes.
     *
     * @param type the type of the field
     * @param name the name of the field
     * @param value the value of the field
     */
    public void buildConfigField(
            @NonNull String type,
            @NonNull String name,
            @NonNull String value)
    
    String type 要創建的字段類型 如上面的String與boolean
    String name 要創建的字段名 如上面的API_HOST與LOG_DEBUG
    String value 創建此字段的值 如上面的"\"http://api.release.com\""與"true"
    但這里要注意一點就是,當創建的類型為String時,定義value的時候要注意加上字符串不能缺少的雙引號"",由于參數本身要傳入的類型也是String,所以我們在添加的時候加上轉義字符
  1. 控制是否自動更新
    一般應用在啟動時都會默認檢查客戶端是否有更新,如果有更新就會提示用戶下載。但是有些渠道和應用市場不允許這種默認行為,所以在適配這些渠道時需要禁止自動更新功能。
    解決的思路是提供一個配置字段,應用啟動的時候檢查該字段的值以決定是否開啟自動更新功能。使用flavor可以完美的解決這類問題。甚至可以在productFlavors對應的渠道號進行區別,例如豌豆莢版默認禁止版本自動更新:

    android {
        defaultConfig {
            buildConfigField "boolean", "AUTO_UPDATES", "true"
        }
        productFlavors {
           wandoujia {
                buildConfigField "boolean", "AUTO_UPDATES", "false"
           }        
        }
    }
    
  2. 多渠道資源文件定制
      客戶端經常會和一些應用分發市場合作,需要在應用的啟動界面中加上第三方市場的Logo,類似這類適配形式還有很多。通常對于不同渠道,我們會區別不同的資源。例如我們一款應用需要在360發布,而應用圖標和歡迎界面要一個360標志的圖或者應用名稱和其他渠道不同,那么這個時候就需要按渠道打包對應的應用圖標和歡迎圖片以及應用名稱了了。
      Gradle在構建應用時,會優先使用flavor所屬dataSet中的同名資源。所以,在flavor的dataSet中添加同名的字符串資源,以覆蓋默認的資源。上面我們已經有針對360的渠道了,就是qihu360,我們只需要在app/src/目錄下添加渠道對應的文件夾qihu360,然后覆蓋對應要覆蓋的內容。下面是定制應用圖標的步驟:

  • 添加qihu360文件夾,那么在 app/src/目錄下面就有 main , androidTest , qihu360,test這四個文件夾了。main 目錄是通用正常渠道包目錄,qihu360是我們需要定制資源的渠道包目錄。如下圖:
    Paste_Image.png
  • 并添加如下應用名字符串資源src/qihu360/res/values/strings.xml:
      <resources>    
      <string name="app_name">360MultiChannelBuild</string>
      </resources>
    
    默認的應用名字符串資源如下(src/main/res/values/strings.xml):
    <resources>    
      <string name="app_name">MultiChannelBuild</string>
    </resources>
    
    最后運行360版本的app即應用名稱顯示成360MultiChannelBuild。
    通過以上例也可以定制其他資源,包括drawablestyles.xml甚至AndroidManifest.xml也都是可以的。即可實現不同渠道不同的應用顯示。
  1. 使用第三方SDK
    某些渠道會要求客戶端嵌入第三方SDK來滿足特定的適配需求。問題的難點在于如何只為特定的渠道添加SDK,其他渠道不引入該SDK。使用flavor可以很好的解決這個問題,下面以為qihu360flavor引入com.qihoo360.union.sdk:union:1.0
    SDK為例進行說明:
android {
    productFlavors {
        qihu360 {
        }
    }
}
...
dependencies {
    //參與編譯但不參與打包
    provided 'com.qihoo360.union.sdk:union:1.0'
    //指定qihu360這個渠道可以打包這個庫
    qihu360Compile 'com.qihoo360.union.sdk:union:1.0'
}

上例添加了名為qihu360的flavor,并且指定編譯和運行時都依賴com.qihoo360.union.sdk:union:1.0。而其他渠道只是在構建的時候依賴該SDK,打包的時候并不會添加它。
接下來,需要在代碼中使用反射技術判斷應用程序是否添加了該SDK,從而決定是否要顯示360 SDK提供的精品應用。部分代碼如下:

class MyActivity extends Activity {
    private boolean useQihuSdk;

    @override
    public void onCreate(Bundle savedInstanceState) {
        try {
            Class.forName("com.qihoo360.union.sdk.UnionManager");
            useQihuSdk = true;
        } catch (ClassNotFoundException ignored) {

        }
    }
}

最后打包運行即可生成包含360精品應用模塊的渠道包了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容