AndroidStudio 多渠道打包實踐總結


寫在前面的話

公司之前使用Ant打包的,一個包平均要10分鐘,三四個包下來,一個小時過去了,作為一名有追求的程序員,這是不能忍受的,所以老大安排我對打包腳本進行改造。

本次改造包括以下內容:

  1. 編譯器由IDEA向AndroidStudio轉換
  2. 增加多渠道打包
  3. 修改打包后的apk文件名
  4. 備份混淆后的mapping文件

接下來就按照這幾塊來細說一下多渠道打包的事

編譯器由IDEA向AndroidStudio轉換

公司的項目原本是在IDEA上開發的,這款軟件是后臺開發的神器,AS在其基礎上增加了一些新功能。編譯的管理也不是Gradle,所以老大想轉到AS開發,然后用Gradle。
在轉的過程中也遇到了一些問題。總結來說這些問題可以分為:分包,多個jar包重復引用,低版本Android support包缺少一些方法,uses-sdk的兼容問題。我把異常信息貼上來就行了,本文重點不在這里。

多jar重復引用
Error:Execution failed for task ':_2C:transformClassesWithJarMergingForRelease'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: io/agora/rtc/IRtcEngineEventHandler$AudioVolumeInfo.class

分包
Error:Execution failed for task ':_2C:transformClassesWithDexForRelease'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

版本過低,缺少方法
Error:(263, 22) 錯誤: 找不到符號
符號:   方法 addDrawerListener(Main)
位置: 類型為DrawerLayout的變量 mDrawerLayout
    
將依賴的minSdkVersion改為與項目一致
<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="22"
    tools:overrideLibrary="org.ffmpeg.android,android.support.v7.recyclerview,android.support.coreui,
        android.support.compat,android.support.v4,android.support.fragment,android.support.mediacompat,
        android.support.coreutils,android.support.v13"/>

增加多渠道打包

除了要增加多渠道打包外,還需要在多渠道中修改一些東西,具體修改的內容如下:

1、首先不同的應用需要修改applicationId(百度地圖,友盟統計,訊飛語音的App_key)
2、用到shareSDK,不同的渠道要替換現在assets這個目錄下面的文件。
3、不同的應用的圖標替換 
4、應用數據的SD卡存儲目錄 
5、應用的AAS接口地址
6、修改生成的apk名字和備份mapping 文件

1 修改applicationId 。修改友盟,微信等第三方App_Key等動態數據都是通過 manifestPlaceholders 占位符的形式進行修改 貼一下圖看一下就懂了

不同的渠道有不同的applicationId,然后修改應用的名字,App_Key PERMISSION這個字段是由于項目中用到了自定義權限,所以要根據applicationId進行修改。到此,第一步完成了,是不是很快?

2 用到shareSDK,不同的應用要替換現在assets這個目錄下面的文件。

3 不同的應用的圖標替換

處理這個問題實質就是資源文件的替換(包括assets 和res 文件的合并)

多說無益,看圖把

這里我用了相對路徑,相對于App項目,這樣子提交到svn的話就不用修改路徑了。通過為每一個渠道指定assets和res的目錄達到編譯的時候動態合并資源

4 應用數據的SD卡存儲目錄

5 應用的AAS接口地址

這個項的要用到buildConfigField 和BuildConfig,在buildConfigField的參數會在編譯的時候生成到BuildConfig中,每一個渠道都會生成一個BuildConfig,通過它來達到動態修改SD卡存儲目錄和AAS接口地址 。

老規矩,上圖

這個是在build.gradle中定義的


看看BuildConfig中的定義


說完這個后我還想說一個,如何在這個BuildConfig中生成一個對象,

解決這個問題的話就想想我們平時實例化一個對象是怎么做的,包名+類 類名 = new 包名+類(),然后看看上圖,就明了。寫全路徑是為了解決導包的問題。

6 修改生成的apk名字和備份mapping 文件
//App同級目錄中新建一個APK文件夾

def apkUrl = file('../APK')
applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    //修改apk名字并輸出到指定位置
                    def fiName
                    if (variant.productFlavors[0].name == "internal") {
                        fiName = "Xiaolaba_a_build_${variant.productFlavors[0].name}_${releaseCode}.apk"
                    } else {
                        fiName = "School_a_v${defaultConfig.versionName}_${variant.productFlavors[0].name}_${releaseCode}.apk"
                    }
                    output.outputFile = new File(apkUrl, fiName)
                    //備份mapping文件
                    if (variant.getBuildType().isMinifyEnabled()) {
                        variant.assemble.doLast {
                            copy {
                                from variant.mappingFile
                                into "${rootDir}/APK"
                                rename { String fileName ->
                                    "mapping-${fiName}.txt"
                                }
                            }
                        }
                    }
                }

            }

總結

到此,多渠道的打包就已經完成了。不過還想提一下如何令build.gradle 這個文件如何變得優雅起來

首先,在app的build.gradle中新建一個config.gradle

其次 在build.gradle中引入config.gradle,project代表當前的build.gradle 定義好這些參數后就可以用了。

這是我在項目中用到的config.gradle xxxxx代表一些敏感信息,所以在這里隱去
ext {
    android = [
            compileSdkVersion: 23,
            buildToolsVersion: "26.0.0",
            minSdkVersion    : 8,
            targetSdkVersion : 23
    ]
    //基礎配置
    dependency = [
            gridlayout  : 'com.android.support:gridlayout-v7:23.4.0',
            recyclerview: 'com.android.support:recyclerview-v7:23.4.0',
            multidex    : 'com.android.support:multidex:1.0.0',
            gson        : 'com.google.code.gson:gson:2.7',
            support     : 'com.android.support:support-v13:23.4.0'
    ]
    //業務地址
    urlSetting = [
            ethernet_addr: "xxxxx",
            dev_addr     : "xxxxx",
            school_addr     : "xxxxx",
            tyd_qdmy_addr:"xxxxx"

    ]
    //多渠道相關
    flavorsSetting = [
            app_id_tyd       : "xxxxx",
            app_name_tyd     : "xxxxx",

            app_id_qdmy      : "xxxxx",
            app_name_qdmy    : "xxxxx",

            app_id_school    : "xxxxx",
            app_name_school  : "xxxxx",
            app_name_internal: "xxxxx"
    ]

    //版本相關
    def versionCode = getVersionCode(releaseTimeAndVersionCode())
    def versionName = getVersionName()

    versionSettting = [
            versionCode: versionCode,
            versionName: versionName
    ]

}


def releaseTimeAndVersionCode() {
    String time = new Date().format("yyMMdd", TimeZone.getTimeZone("UTC"))
    return time.substring(1, time.length())
}

def getVersionCode(String version) {
    return Integer.parseInt(version)
}

def getVersionName() {
    def versionFile = file('version.properties')
    if (versionFile.exists()) {
        def Properties versionProps = new Properties()
        versionProps.load(new FileInputStream(versionFile))
        def versionCode = versionProps['versionName'].toString()
        return versionCode
    } else {
        throw new GradleException("Could not find version.properties!")
    }
}

好了,多渠道打包總結就到此結束了。有不明白的地請留言。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容