今天写一篇文章来总结下android批量打渠道包美团版本。之前项目上一直用的是gradle 批量打包方式,那个速度啊真是令人发指,15个渠道得跑上半个小时,出去吃顿饭回来,还在跑。特别是赶上项目上线的话,如果给测试提交了正式版本1.0,突然发现有小bug要修复,修复后又得重新批量打包半个小时。。。。无语啦。。。真佩服以前的耐心。。。。好了今天来看下打包方案 - 美团多渠道打包方案。至于为撒是美团,应该是这个方案是美团的哪一位大神放出来的吧。

为什么要打渠道包

为什么要渠道打包,一个包不是挺好的吗,一个包也可以发布到各个应用市场嘛?以前刚入门时候也是傻乎乎的这么想的。如果现在你老板提出这样需求场景:亮仔呀,我想知道我们的APP在哪个应用市场渠道下载的最多,我们以后就重点推广这个渠道,用钱砸到排名前面!!! 亮仔傻眼了!!—— 所以不同渠道打包主要用来做统计分析,特别是游戏应用,特别注意哪个渠道推广的最有效。

下面是友盟平台,APP统计各个渠道的分析图:

TIM图片20170620101652.png

从统计图可以看出APP在各个渠道的用户、活跃度、启动次数、活动时长....还是比较详细的,对运营团队有着很大的指导作用哈。

怎么打渠道包

怎么渠道打包呢?亮仔就开始想了:这还不简单,三步搞定:

1.我在Adminifest.xml文件里面配一个meta-data值,这个值写死成某个渠道;

2.在用户安装了我们的APP后,我获取这个写死的渠道值然后上传到后台;

3.我挨个修改meta-data值,改成各个渠道然后编译打包10分钟搞定;

很快亮仔就开始上手,很快实现了老板提出的需求!!! 好景不长... 老板:亮仔啊,我们这个应用下载量不给力啊,推广不够啊,这样我们把我们APP发到市场上所有渠道上,广撒网捕鱼嘛,也不多就100多个渠道吧!!! 亮仔慌了:我擦,我打一个包需要2分钟,100个包 3个多小时啊 这一天光打包了.....

所以基于上面的场景,我们发现主要有两个问题:

打包的本质是将渠道标识传递给后台

这一步已经有第三方平台帮我们做了,实现的思路应该也也差不多,我们集成友盟的渠道统计分析即可。没有必要写一套自己的渠道统计分析。友盟渠道统计接入传送门>>

怎样快速打包

为什么打包会花那么长时间?因为每个渠道打一次包,就要重新编译一次,所以耗时长。其实只要想办法将打好的一个包,替换里面的meta-data值即可。我们来看下美团多渠道打包是怎么做的:

1.首先你需要安装python环境

不要被python环境搭建吓到,其实就跟安装一个普通的exe软件差不多,下一步。。安装后不需要配置什么环境变量之类。 [python下载传送门 >>](https://www.python.org/downloads/)

2.项目中接入友盟统计

2.1 申请友盟的账号

在Adminifest.xml中配置友盟ID和渠道标识

android:name="UMENG_APPKEY"

android:value="***************">

android:name="UMENG_CHANNEL"

android:value="baidu" />

2.2 应用启动时上传渠道标识给友盟

ChannelUtil 是封装的一个获取渠道标识的工具类

public class MyApplication extends Application {

@Override

public void onCreate() {

super.onCreate();

String channel=ChannelUtil.getChannel(this, "default channel");//获取渠道名

AnalyticsConfig.setChannel(channel);//调用umeng api设置umeng渠道

}

}

ChaneUtil工具类直接偷来的~~

import java.io.IOException;

import java.util.Enumeration;

import java.util.zip.ZipEntry;

import java.util.zip.ZipFile;

import android.content.Context;

import android.content.SharedPreferences;

import android.content.SharedPreferences.Editor;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageManager.NameNotFoundException;

import android.preference.PreferenceManager;

import android.text.TextUtils;

public class ChannelUtil {

private static final String CHANNEL_KEY = "cztchannel";

private static final String CHANNEL_VERSION_KEY = "cztchannel_version";

private static String mChannel;

/**

* 返回市场。 如果获取失败返回""

* @param context

* @return

*/

public static String getChannel(Context context){

return getChannel(context, "");

}

/**

* 返回市场。 如果获取失败返回defaultChannel

* @param context

* @param defaultChannel

* @return

*/

public static String getChannel(Context context, String defaultChannel) {

//内存中获取

if(!TextUtils.isEmpty(mChannel)){

return mChannel;

}

//sp中获取

mChannel = getChannelBySharedPreferences(context);

if(!TextUtils.isEmpty(mChannel)){

return mChannel;

}

//从apk中获取

mChannel = getChannelFromApk(context, CHANNEL_KEY);

if(!TextUtils.isEmpty(mChannel)){

//保存sp中备用

saveChannelBySharedPreferences(context, mChannel);

return mChannel;

}

//全部获取失败

return defaultChannel;

}

/**

* 从apk中获取版本信息

* @param context

* @param channelKey

* @return

*/

private static String getChannelFromApk(Context context, String channelKey) {

//从apk包中获取

ApplicationInfo appinfo = context.getApplicationInfo();

String sourceDir = appinfo.sourceDir;

//默认放在meta-inf/里, 所以需要再拼接一下

String key = "META-INF/" + channelKey;

String ret = "";

ZipFile zipfile = null;

try {

zipfile = new ZipFile(sourceDir);

Enumeration> entries = zipfile.entries();

while (entries.hasMoreElements()) {

ZipEntry entry = ((ZipEntry) entries.nextElement());

String entryName = entry.getName();

if (entryName.startsWith(key)) {

ret = entryName;

break;

}

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (zipfile != null) {

try {

zipfile.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

String[] split = ret.split("_");

String channel = "";

if (split != null && split.length >= 2) {

channel = ret.substring(split[0].length() + 1);

}

return channel;

}

/**

* 本地保存channel & 对应版本号

* @param context

* @param channel

*/

private static void saveChannelBySharedPreferences(Context context, String channel){

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);

Editor editor = sp.edit();

editor.putString(CHANNEL_KEY, channel);

editor.putInt(CHANNEL_VERSION_KEY, getVersionCode(context));

editor.commit();

}

/**

* 从sp中获取channel

* @param context

* @return 为空表示获取异常、sp中的值已经失效、sp中没有此值

*/

private static String getChannelBySharedPreferences(Context context){

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);

int currentVersionCode = getVersionCode(context);

if(currentVersionCode == -1){

//获取错误

return "";

}

int versionCodeSaved = sp.getInt(CHANNEL_VERSION_KEY, -1);

if(versionCodeSaved == -1){

//本地没有存储的channel对应的版本号

//第一次使用 或者 原先存储版本号异常

return "";

}

if(currentVersionCode != versionCodeSaved){

return "";

}

return sp.getString(CHANNEL_KEY, "");

}

/**

* 从包信息中获取版本号

* @param context

* @return

*/

private static int getVersionCode(Context context){

try{

return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;

}catch(NameNotFoundException e) {

e.printStackTrace();

}

return -1;

}

}

3.运行打包脚本打包

3.1 下载打包脚本

下载解压

3.2 配置渠道

配置渠道

3.3 拷贝apk包到PythonTool目录下(与py同级)

apk包放置目录

3.4 运行py脚本 MultiChannelBuildTool.py即可打包完成。

(生成的渠道apk包在output_** 目录下)

打包完成

ok,写完啦!刚开始练习写总结文章,有讲的不清楚的,欢迎指正!!

搬砖啦

android打包工具多渠道批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案...相关推荐

  1. android 美团批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案

    今天写一篇文章来总结下android批量打渠道包美团版本.之前项目上一直用的是gradle 批量打包方式,那个速度啊真是令人发指,15个渠道得跑上半个小时,出去吃顿饭回来,还在跑.特别是赶上项目上线的 ...

  2. Shiro第一个程序:官方快速入门程序Qucickstart详解教程

    目录 一.下载解压 二.第一个Shiro程序 1. 导入依赖 2. 配置shiro配置文件 3. Quickstart.java 4. 启动测试 三.shiro.ini分析 四.Quickstart. ...

  3. android收藏功能demo,Android使用Realm数据库实现App中的收藏功能(代码详解)

    前 言 App数据持久化功能是每个App必不可少的功能,而Android最常用的数据持久化方式主要有以下的五种方式: 使用SharedPreferences存储数据: 文件存储数据: SQLite数据 ...

  4. 详解vue静态资源打包中的坑与解决方案

    详解vue静态资源打包中的坑与解决方案 参考文章: (1)详解vue静态资源打包中的坑与解决方案 (2)https://www.cnblogs.com/goloving/p/8904545.html ...

  5. 上传服务器后字体文件丢失,详解Vue+elementUI build打包部署后字体图标丢失问题...

    错误描述: Vue+elementUI  build打包部署后字体图标丢失,控制台显示文件element-icons.woff和element-icons.ttf文件404 错误展现: 控制台报错截图 ...

  6. 基于百度地图实现Android定位功能实现(详解+教程)

    基于百度地图实现Android定位功能实现(详解+教程) 1.初始化 (一)获取到SHA1 (1)找到View中的Tool Windows并打开Terminal (2)找到你的jdk的bin目录,小编 ...

  7. Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(一)

    文章大纲 引言 一.Android Storage Access Framework 二.Storage Access Framework 的主要角色成员 1.Document Provider 文件 ...

  8. Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(二)

    文章大纲 引言 一.DirectFragment 1.当选中DirectoryFragment中RecyclerView的Item时 2.选中DirectoryFragment中RecyclerVie ...

  9. kettle工具下载、安装、数据迁移、定时任务详解

    kettle工具下载.安装.数据迁移.定时任务详解 篇幅有点长,将这五个内容放在了一篇文章里,其中最主要的是数据迁移和定时任务 目录 目录 一.简单介绍 二.下载 三.安装 四.数据迁移:包括单表整体 ...

最新文章

  1. 集合视图UICollectionView 介绍及其示例程序
  2. Mac OS X安装 ffmpeg
  3. 数据库的事务隔离级别
  4. fp16和fp32,神经网络混合精度训练,PYTORCH 采用FP16,Libtorch采用FP16,神经网络混合精度三种避免损失,TensorRT模型转换及部署(一)
  5. 电商行业用户画像分析案例
  6. Vue----组件库
  7. 目标检测中PR曲线和mAP
  8. windows图片查看器背景颜色更改
  9. 常用制作钓鱼网站的工具
  10. Easypoi模版形式导出excel导出图片
  11. android 驱动程序,安卓设备安装USB驱动程序教程
  12. 十分钟看懂时序数据库(I)-存储
  13. 苹果手机微信记录恢复最简单的恢复方法
  14. 【Windows】【VS】error C2220: 以下警告被视为错误
  15. android 图片分析,Android ImageView圆形头像 图片完全解析
  16. 机器学习:simple linear iterative clustering (SLIC) 算法
  17. linux joe编辑器,Linux joe命令
  18. 离散傅里叶变换 (DFT)、快速傅里叶变换 (FFT)
  19. 一般早餐店卖不了的包子、馒头是怎么处理的?
  20. 177本名著浓缩成了177句话!经典收藏!太有道理了!

热门文章

  1. php: +1天, +3个月, strtotime(): +1 day, +3 month
  2. Linux 输入子系统原理理解(原创)
  3. WCF系列(1)—— CustomBehavior 入门
  4. brew 安装 mysql5.7_Mac——brew替换源地址安装配置mysql@5.7版本
  5. Slimming Down Windows XP The Complete Guide 【 10章完整版 】
  6. const的用法以及与define使用的区别
  7. 微信小程序怎么取mysql_微信小程序如何加载数据库真实数据?
  8. python发钉钉消息_Python调用钉钉机器人推送消息
  9. 搭建GitLab+Jenkins持续集成环境图文教程
  10. Android File.listFiles()返回null问题