首页 > 代码库 > Android多渠道批量打包

Android多渠道批量打包

如若感觉排版不舒服,请移步Android多渠道批量打包

1、为什么要进行多渠道打包?

  安卓应用商店(一个商店也叫做一个渠道,如豌豆荚,360手机助手,应用宝)众多。大大小小几百个,每当我们发新版本号时。须要将Androidclient分发到各个应用市场。为了统计这些市场的效果(下载量、活跃数等)。须要有一种方法来唯一标识它们,所以才有了多渠道打包。

2、怎样统计各个渠道的下载量、活跃数?

  如今有比較成熟的第三方应用帮我们实现统计功能(比方友盟),统计的本质就是收集用户信息传输到后台,后台生成报表,帮助我们跟踪分析并完好app。通过android系统的方法已经能够获取到引用版本号号,版本号名称,系统版本号。机型等各种信息,只有应用商店(渠道)的信息我们是没有办法从系统获取到的。所以我们就人为的在apk里面加入渠道信息(事实上就用一个字段进行标识。如wandoujia360yingyongbao),我们仅仅要把这些信息打包到apk文件并将信息传输到后台,后台依据这个标识,能够统计各个渠道的下载量了。
多渠道打包仅仅须要关注两件事情:
1. 将渠道信息写入apk文件
2. 将apk中的渠道信息传输到统计后台

3、以下我们主要讲述两种多渠道打包方式。

* 3.1、美团Android自己主动化之旅—生成渠道包*

过程例如以下:
1. 下载安装python环境 Python下载地址;
2. 下载python脚本 AndroidMultiChannelBuildTool
3. 将ChannelUtil.java代码集成到project里面,在app启动时获取渠道号传送给后台(如友盟: AnalyticsConfig.setChannel(ChannelUtil.getChannel(this)););
4. 在PythonTool/Info/channel.txt中编辑渠道列表。以换行隔开。示比例如以下:

samsungapps
hiapk
anzhi
360cn
xiaomi
myapp
91com
gfan
appchina
nduoa
3gcn
mumayi
10086com
wostore
189store
lenovomm
hicloud
meizu
baidu
googleplay
wandou

5. 打包apk,将apk文件拷贝到PythonTool文件夹下(与py同级),执行(直接双击.py文件或者在命令行输入 python MultiChannelBuildTool.py )py脚本就可以打包完毕。(生成的渠道apk包在output_** 文件夹下)

技术分享

技术分享

3.2、使用Gradle进行多渠道批量打包

  1. 通常都是在在AndroidManifest.xml中加入渠道区分标识写入一个meta标签:
<meta-data   
     android:name="channel"    
     android:value=http://www.mamicode.com/"${channel}" 
/>
  1. 在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打签名包时就可以选择设置渠道:
技术分享

  1. 在代码中获取渠道信息:
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。

技术分享

4.APP定制–适配渠道包

可參考美团技术文档之美团Android自己主动化之旅—适配渠道包
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"
        } // 360手机助手
        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 了。

  1. 控制是否自己主动更新
    一般应用在启动时都会默认检查client是否有更新,如果有更新就会提示用户下载。

    可是有些渠道和应用市场不同意这样的默认行为,所以在适配这些渠道时须要禁止自己主动更新功能。
    解决的思路是提供一个配置字段,应用启动的时候检查该字段的值以决定是否开启自己主动更新功能。使用flavor能够完美的解决这类问题。甚至能够在productFlavors相应的渠道号进行差别。比如豌豆荚版默认禁止版本号自己主动更新:

    android {
               defaultConfig {
               buildConfigField "boolean", "AUTO_UPDATES", "true"
               }
              productFlavors {
                 wandoujia {
                     buildConfigField "boolean", "AUTO_UPDATES", "false"
                 }        
              }
        }
  1. 多渠道资源文件处理
      client常常会和一些应用分发市场合作。须要在应用的启动界面中加上第三方市场的Logo,相似这类适配形式还有非常多。

    通常对于不同渠道。我们会差别不同的资源。比如我们一款应用须要在360公布。而应用图标和欢迎界面要一个360标志的图或者应用名称和其它渠道不同。那么这个时候就须要按渠道打包相应的应用图标和欢迎图片以及应用名称了了。
      Gradle在构建应用时。会优先使用flavor所属dataSet中的同名资源。所以,在flavor的dataSet中加入同名的字符串资源。以覆盖默认的资源。上面我们已经有针对360的渠道了,就是qihu360,我们仅仅须要在app/src/文件夹下加入渠道相应的文件夹qihu360,然后覆盖相应要覆盖的内容。以下是定制应用图标的步骤:

    • 加入qihu360文件夹,那么在 app/src/文件夹以下就有 main , androidTest , qihu360,test这四个文件夹了。main 文件夹是通用正常渠道包文件夹,qihu360是我们须要定制资源的渠道包文件夹。例如以下图:
      技术分享
    • 并加入例如以下应用名字符串资源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也都是能够的。

就可以实现不同渠道不同的应用显示。


5. 使用第三方SDK(来自美团Android自己主动化之旅—适配渠道包)
某些渠道会要求client嵌入第三方SDK来满足特定的适配需求。

比方360应用市场要求美团团购Androidclient的精品应用模块使用他们提供的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精品应用模块的渠道包了。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

Android多渠道批量打包