Android 多版本 多渠道打包

在平时的Android开发中,基于某些需求我们可能要针对一份APK代码打出多个不同的APK包来实现一些通过换肤换名称达到不同APK发布的效果,然后针对这些不同APK再进行一次打多个渠道包等需求,该怎么样通过一份代码一次性打出多个APK包?如何快速的打出多个渠道包?这是我们需要去研究并解决的问题。

一、简述

1.多版本

基于productFlavors
  本身productFlavors是一个多渠道打包方式,为了能够替换资源我们把不同版本APK包通过这个方式来区分,这里我们简单用GanHuo和GanHuo2来作为两个不同APP

2.多渠道

  多渠道打包方式可以参考我的之前一篇关于Python多渠道打包方式

二、示例

1.配置build.gradle

(1)配置app目录下面的build.gradle文件

GanHuo {
            applicationId "com.ganhuo"
            resValue "string", "appName", '"干货"'
            buildConfigField "boolean", "AUTO_UPDATES", "false"
            manifestPlaceholders = [
                    app_name    : "Ganhuo",
                    app_icon    : "@mipmap/icon",
                    appid       : "com.ganhuo",
                    umeng_secret: "***",
                    app_scheme  : "ganhuo"
               ]
        }

        GanHuo2{
            applicationId "com.ganhuo2"
            resValue "string", "appName", '"干货2"'
            manifestPlaceholders = [
                    app_name: "GanHuo2",
                    app_icon: "@mipmap/icon",
                    appid: "com.ganhuo2",
                    umeng_secret: "***",
                    app_scheme  : "ganhuo2"
            ]
        }

manifestPlaceholders里面相关的参数可以让我们在manifest通过占位符的方式去替换

<application
        android:name=".Application"
        android:allowBackup="false"
        android:hardwareAccelerated="true"
        android:icon="${app_icon}"
        android:label="${app_name}"
        android:largeHeap="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:theme="@style/ApplicationTheme">
<activity
            android:name=".MainActivity"
            android:hardwareAccelerated="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="${app_scheme}" />
            </intent-filter>
        </activity>
<!-- 友盟Appkey -->
        <meta-data
            android:name="UMENG_APPKEY"
            android:value="${umeng_secret}" />
    </application>

(2)定义res对象

在build.gradle 的productFlavors 里面定义String

GanHuo {
        resValue "string", "appName", '"干货"'
}

然后在strings.xml文件里面引用

<resources>
    <string name="app_name">@string/appName</string>`
</resource>

(3)定义变量
我们有时候可能需要定义一些公共变量来判断是不是测试环境或者是生产环境,或者是需要一些公用变量,我们可以定义一个叫跟GanHuo同级的defaultConfig的标签,标签里面可以放所有现场共用的属性和变量,代码如下:

android{
    defaultConfig{
        //存放公共变量
        buildConfigField 'Boolean', 'AUTO_UPDATES', 'true'
    }
    GanHuo{
       buildConfigField 'String', 'ENVIRONMENT', '"PRODUCT"'
    }
    GanHuo2{
      buildConfigField 'String', 'ENVIRONMENT', '"TEST"'
    }
}

(4)配置资源文件

如果不同的渠道包需要不同的相关icon,可以通过下图的方式进行配置:


image.png

2.解除微信回调的Activity必须在包名.wxapi下的限制

在分不同包名的时候,由于用到了微信授权、分享相关微信功能,微信回调的Activity必须在包名.wxapi,为了解决这个问题,我们需要创建多个包名,里面创建WxEntryActivity,然后在AndroidManifest注册多个activity。这样有新的包名就需要新增一个微信回调,非常繁琐。为了偷懒,我们需要有一劳永逸的方法。这时候想到了我们在处理provider的时候由于手机里面只允许同样的provider存在一个,所以我们做了相应的处理


image.png

有没有类似这种操作呢,这时候发现我们可以通过activity-alias的targetActivity来实现,代码如下:

<!-- 微信分享回调 通过别名的方式来规避多个不同版本包需要新建多个微信回调文件问题-->
        <activity android:name=".base.AbsWXEntryActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:exported="true"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" ></activity>
        <activity-alias
            android:name="${applicationId}.wxapi.WXEntryActivity"
            android:targetActivity=".base.AbsWXEntryActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:exported="true"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity-alias>

activity-alias里面的name只是一个虚拟的占位符而已,会被重定向到实际处理的targetactivity

这里记录一下通过android studio 3.0编译过程中遇到的几个问题
(1)Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
在使用android studio 3.0的时候,gradle版本需要升级到3.5版本才能编译。这个错误的大致意思是:所有的flavors都必须属于同一个风格。通过查阅了资料之后发现Plugin 3.0.0之后有一种自动匹配消耗库的机制,便于debug variant 自动消耗一个库,然后就是必须要所有的flavor 都属于同一个维度。为了避免flavor 不同产生误差的问题,应该在所有的库模块都使用同一个foo尺寸。对此,我也不是很理解,庆幸的是有给出解决方案

在主app的build.gradle里面的
 defaultConfig {
 targetSdkVersion:***
minSdkVersion :***
versionCode:***
 versionName :***
//版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了
flavorDimensions "versionCode"

}

(2)gradle 打包
  gradle打包,自定义apk名称代码报错(Cannot set the value of read-only property ‘outputFile’ )
Error:(56, 0) Cannot set the value of read-only property ‘outputFile’ for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
解决:在app的buide.gradle修改3.0之前输出自定义apk名字的代码,代码如下:

//3.0之前打包输出自定义apk名称代码
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith(".apk")) {
                def fileName = "Android_${variant.productFlavors[0].name}_v${defaultConfig.versionName}.apk"
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
//3.0之后打包输出自定义apk名称代码
    android.applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "Android_${variant.productFlavors[0].name}_v${defaultConfig.versionName}.apk"
        }
    }

如果需要修改manifest内容,可以看我这篇文章通过gradle 动态修改AndroidManifest.xml文件

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容