android打包工具多渠道批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案...
今天写一篇文章来总结下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 快速渠道批量打包详解教程-美团多渠道打包方案...相关推荐
- android 美团批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案
今天写一篇文章来总结下android批量打渠道包美团版本.之前项目上一直用的是gradle 批量打包方式,那个速度啊真是令人发指,15个渠道得跑上半个小时,出去吃顿饭回来,还在跑.特别是赶上项目上线的 ...
- Shiro第一个程序:官方快速入门程序Qucickstart详解教程
目录 一.下载解压 二.第一个Shiro程序 1. 导入依赖 2. 配置shiro配置文件 3. Quickstart.java 4. 启动测试 三.shiro.ini分析 四.Quickstart. ...
- android收藏功能demo,Android使用Realm数据库实现App中的收藏功能(代码详解)
前 言 App数据持久化功能是每个App必不可少的功能,而Android最常用的数据持久化方式主要有以下的五种方式: 使用SharedPreferences存储数据: 文件存储数据: SQLite数据 ...
- 详解vue静态资源打包中的坑与解决方案
详解vue静态资源打包中的坑与解决方案 参考文章: (1)详解vue静态资源打包中的坑与解决方案 (2)https://www.cnblogs.com/goloving/p/8904545.html ...
- 上传服务器后字体文件丢失,详解Vue+elementUI build打包部署后字体图标丢失问题...
错误描述: Vue+elementUI build打包部署后字体图标丢失,控制台显示文件element-icons.woff和element-icons.ttf文件404 错误展现: 控制台报错截图 ...
- 基于百度地图实现Android定位功能实现(详解+教程)
基于百度地图实现Android定位功能实现(详解+教程) 1.初始化 (一)获取到SHA1 (1)找到View中的Tool Windows并打开Terminal (2)找到你的jdk的bin目录,小编 ...
- Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(一)
文章大纲 引言 一.Android Storage Access Framework 二.Storage Access Framework 的主要角色成员 1.Document Provider 文件 ...
- Android 进阶——Framework 核心之Android Storage Access Framework(SAF)存储访问框架机制详解(二)
文章大纲 引言 一.DirectFragment 1.当选中DirectoryFragment中RecyclerView的Item时 2.选中DirectoryFragment中RecyclerVie ...
- kettle工具下载、安装、数据迁移、定时任务详解
kettle工具下载.安装.数据迁移.定时任务详解 篇幅有点长,将这五个内容放在了一篇文章里,其中最主要的是数据迁移和定时任务 目录 目录 一.简单介绍 二.下载 三.安装 四.数据迁移:包括单表整体 ...
最新文章
- 集合视图UICollectionView 介绍及其示例程序
- Mac OS X安装 ffmpeg
- 数据库的事务隔离级别
- fp16和fp32,神经网络混合精度训练,PYTORCH 采用FP16,Libtorch采用FP16,神经网络混合精度三种避免损失,TensorRT模型转换及部署(一)
- 电商行业用户画像分析案例
- Vue----组件库
- 目标检测中PR曲线和mAP
- windows图片查看器背景颜色更改
- 常用制作钓鱼网站的工具
- Easypoi模版形式导出excel导出图片
- android 驱动程序,安卓设备安装USB驱动程序教程
- 十分钟看懂时序数据库(I)-存储
- 苹果手机微信记录恢复最简单的恢复方法
- 【Windows】【VS】error C2220: 以下警告被视为错误
- android 图片分析,Android ImageView圆形头像 图片完全解析
- 机器学习:simple linear iterative clustering (SLIC) 算法
- linux joe编辑器,Linux joe命令
- 离散傅里叶变换 (DFT)、快速傅里叶变换 (FFT)
- 一般早餐店卖不了的包子、馒头是怎么处理的?
- 177本名著浓缩成了177句话!经典收藏!太有道理了!
热门文章
- php: +1天, +3个月, strtotime(): +1 day, +3 month
- Linux 输入子系统原理理解(原创)
- WCF系列(1)—— CustomBehavior 入门
- brew 安装 mysql5.7_Mac——brew替换源地址安装配置mysql@5.7版本
- Slimming Down Windows XP The Complete Guide 【 10章完整版 】
- const的用法以及与define使用的区别
- 微信小程序怎么取mysql_微信小程序如何加载数据库真实数据?
- python发钉钉消息_Python调用钉钉机器人推送消息
- 搭建GitLab+Jenkins持续集成环境图文教程
- Android File.listFiles()返回null问题