在网上看到一篇多渠道打包APK的,思路是没问题的,原文地址:http://www.cnblogs.com/yyyyy5101/archive/2012/10/23/2735912.html

下面是具体内容:

android应用上传时,需要区分开每个渠道。一般都会在配置文件中更改一个渠道id,如果有多个渠道,手动修改并生成apk的话会非常麻烦,而且增大出错概率。

在这分享一个打包工具类.

我们项目中使用的umeng做统计分析工具, umeng在分渠道打包的时候需要修改manifest.xml中的

<meta-data android:name="UMENG_CHANNEL" android:value="@string/channel_name" /> value值。

该值放到了strings.xml中<string name="channel_name">app_channel</string>,所以在编译的时候只需修改app_channel。

下面是工具类,直接运行即可.

package com.yang.main;import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/*** @description: android渠道打包工具类,确保路径填写无误,渠道名称填入channels中* @author: yangyang@duitang.com* @time:    2012-10-23下午5:17:47*/
public class CompiledApkUpdate {private static final String androidSDK_PATH = "D:\\android\\android-sdk-windows\\";        //android SDK路径public static final String APK_NAME = "duitang.apk";public static final String PROJECT_LIBARY = "";public static final String PROJECT_PATH = "D:\\android\\workspace\\tmp\\duitang\\";        //要打包的工程路径public static final String APK_PATH = "D:\\android\\workspace\\tmp\\apk\\duitang_";        //打包后存放apk的路径  duitang_是前缀private static final String apk_PATH_keystore = "D:\\android\\keystore\\bb";        //apk签名文件路径private static final String channelFlag = "app_channel";//    public static String[] channels = {"duitang"}; private static String currentChannelName = "";public static String[] channels = {"duitang","91","360","QQ","jifeng","anzhuo","anzhi","youyi","appchina","wangyi","baidu","souhu","3g","nduo","xiaomi","huawei","meizu","lianxiang","aliyun","taobao","google","nearme","mumayi","wandoujia","crosscat","dangle","maopao","feiliu"}; public static void main(String[] args) { replaceChannel();}/*** 替换渠道名称*/public static void replaceChannel() {try {String outPath = PROJECT_PATH + "res\\values\\strings.xml"; // 输出文件位置String content = read(outPath);for(int channelid=0;channelid<channels.length;channelid++){String tmpContent = content;tmpContent = tmpContent.replaceFirst(channelFlag, channels[channelid]);currentChannelName = channels[channelid];write(tmpContent,outPath);System.out.println("replace channel name over...");packageRes(); // 一次渠道号的更改完成。可以进行打包了。createUnsignedApk();signedApk(channelid);}write(content,outPath);        //完成后还原channel_nameSystem.out.println("execute over!");} catch (Exception e) {e.printStackTrace();}}/*** class文件打包成classes.dex*/public static void packageDex(){try { System.out.println("dx.bat start...");Process process = Runtime.getRuntime().exec(androidSDK_PATH+"platform-tools\\dx.bat --dex --output="+PROJECT_PATH+"bin\\classes.dex "+PROJECT_PATH+"bin\\classes "+PROJECT_PATH+"libs\\*.jar"); new MyThread(process.getErrorStream()).start();new MyThread(process.getInputStream()).start();process.waitFor();  process.destroy();  System.out.println("dx.bat over...");} catch (Exception e) { e.printStackTrace(); } }/*** res assets文件打包成res.zip*/public static void packageRes(){try{System.out.println(currentChannelName+" create resources.ap");String library = "";if(PROJECT_LIBARY!=null&&!PROJECT_LIBARY.equals("")){library = "-S " + PROJECT_LIBARY + "res ";}Process process = null;process = Runtime.getRuntime().exec(  androidSDK_PATH+ "platform-tools\\aapt.exe package -f " +"-M " + PROJECT_PATH + "AndroidManifest.xml " +            //-M 指定配置文件"-S " + PROJECT_PATH + "res " +                            //-S 指定资源文件library +"-A " + PROJECT_PATH + "assets " +                        //-A 指定assets"-I " + androidSDK_PATH + "platforms\\android-16\\android.jar " +    //-I 指定android类"-F " + PROJECT_PATH + "bin\\resources.ap_ --auto-add-overlay"); // 将资源文件打包resources.ap_new MyThread(process.getErrorStream()).start();new MyThread(process.getInputStream()).start();process.waitFor();process.destroy();System.out.println(currentChannelName+" resources.ap over...");}catch(Exception e){e.printStackTrace();}}/*** classes.dex res.zip AndroidManifest.xml组合成未签名的apk*/public static void createUnsignedApk(){try{System.out.println(currentChannelName+" createUnsignedApk start");Process process = null;process = Runtime.getRuntime().exec(androidSDK_PATH+ "tools\\apkbuilder.bat "+ PROJECT_PATH + "bin\\"+APK_NAME+" -u -z "+ PROJECT_PATH + "bin\\resources.ap_ -f "+ PROJECT_PATH + "bin\\classes.dex"); // 生成未签名的apknew MyThread(process.getErrorStream()).start();new MyThread(process.getErrorStream()).start();process.waitFor();process.destroy();System.out.println(currentChannelName+" createUnsignedApk over");}catch(Exception e){e.printStackTrace();}}/*** 签名apk*/public static void signedApk(int channelid){try{System.out.println(currentChannelName+" signed apk start");Process process = null;String jarsigner;jarsigner = "jarsigner -keystore "+apk_PATH_keystore+" -storepass ***** -keypass ****** " +"-signedjar "+ APK_PATH+ channels[channelid]+ ".apk "+ PROJECT_PATH+ "bin\\"+APK_NAME+" *****";            //签名apkprocess = Runtime.getRuntime().exec(jarsigner); // 对apk进行签名new MyThread(process.getErrorStream()).start();new MyThread(process.getInputStream()).start();process.waitFor();process.destroy();System.out.println(currentChannelName+" signed apk over"); // 一条渠道的打包完成。文件会输出到指定目录}catch(Exception e){e.printStackTrace();}}public static String read(String path) {StringBuffer res = new StringBuffer();String line = null;try {BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path),"UTF-8"));while ((line = reader.readLine()) != null) {res.append(line + "\n");}reader.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return res.toString();}public static boolean write(String cont, String dist) {try {OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(dist)),"utf-8");writer.write(cont);writer.flush();writer.close();return true;} catch (IOException e) {e.printStackTrace();return false;}}public static class MyThread extends Thread{BufferedReader bf;public MyThread(InputStream input) {bf = new BufferedReader(new InputStreamReader(input));}public void run() {String line;try {line = bf.readLine();while (line != null) {System.out.println(line);line = bf.readLine();}} catch (IOException e) {e.printStackTrace();}}}
}

注意事项:

1. 正确设置各个path路径.

2. channelFlag的值要与 strings.xml 中channel_name的value一致.

3. 运行java文件是先运行一下android工程,确保bin目录下有最新的apk.

4. 运行过程中不要手动停止,如手动停止,再次运行时请检查strings.xml中channel_name的value值,如不为app_channel,请修改

5. 如有error: Error parsing XML: not well-formed (invalid token)类似错误,注意设置字符编码

Android多渠道打包APK相关推荐

  1. android 渠道方案,Android多渠道打包时获取当前渠道的方法

    作为Androidapp,发布多个分发平台是常规操作.然后,有时由于个渠道面对的用户不同,或平台审核标准不同,需要在各渠道使用不同的业务逻辑,这就需要根据渠道使用选择差异化代码. 这里把简单的代码记一 ...

  2. Android多渠道打包配置

    Android多渠道打包配置 之前为了在同一台手机能同时安装测试包和生产包,采用配置buildType的方式来实现,相比于flavor,感觉是挺轻量又恰到好处的配置,具体见通过配置applicatio ...

  3. Android 多渠道打包配置,亲测,全集

    Android 多渠道打包配置 前言 为统计渠道数据和利用渠道进行操作,需进行渠道打包.本文目旨在熟悉原生gradle多渠道打包的方式,了解android基本的gradle构建配置,熟悉代码构建目录, ...

  4. android 多渠道资源,Android多渠道打包

    Android多渠道打包 概述 每当发新版本时,Android客户端会被分发到各个应用市场,比如豌豆荚,360手机助手等.为了统计这些市场的效果(活跃数,下单数等),需要有一种方法来唯一标识它们.客户 ...

  5. android 渠道打包工具,Walle —— Android多渠道打包神器

    图片只为致敬斯坦·李 Walle为了android多渠道打包而生的工具,废话不多说直接上用法 配置build.gradle 在项目的build.gradle文件中添加walle插件依赖 depende ...

  6. Unity 多渠道打包 APK

    Unity 多渠道打包 APK 一个工程打包给 N 个渠道,每个渠道有自己的 应用名.应用Icon.包名.keystore.各种需要接入的SDK,甚至每个渠道有单独的资源等等 为了方便.省事.省时,决 ...

  7. Android多渠道打包的几种常用工具

    Android项目开发完,多渠道打包是必不可少的环节.其原理在于,通过在Android安卓包中添加不同的标识,区分各个渠道下载来源,用于统计App在不同应用市场或渠道合作中的各项数据. 工欲善其事,必 ...

  8. 几个常见的Android多渠道打包工具介绍

    Android项目开发完,多途径打包是必不可少的环节.其原理在于,通过在Android安卓包中增加不同的标识,区别各个途径下载来源,用于计算App在不同使用市场或途径合作中的各项数据. 工欲善其事,必 ...

  9. android app 马甲包,关于Android多渠道打包和马甲包问题

    多渠道打包 最近项目用到多渠道打包,虽然网上又很多资料, 但是我在实际使用的过程中还是遇到了些问题, 在这里记录下,希望能帮助到你! 首先配置你的渠道信息 : 配置渠道信息 这个时候渠道使用的签名配置 ...

最新文章

  1. Notepad++ 开启「切分窗口」同时检视、比对两份文件
  2. ubuntu 开启php mysql扩展_linux(ubuntu/centos)、windows安装php-zip扩展
  3. Python 安装路径, dist-packages 和 site-packages 区别
  4. 使用Velocity(VTL)调用自定义C# .net 中的方法
  5. 【转】JavaScript中的this关键字使用的四种调用模式
  6. 【实战】颠覆银行基础架构的区块链
  7. 热点热词 新闻热点 最新新闻数据API接口-天狗热点热词开放平台
  8. java getResourceAsStream方法
  9. 为用户增加sudo权限(修改sudoers文件)
  10. vector 简单使用
  11. 猜你喜欢”推荐算法大赛冠军分享
  12. 计算机软件著作权收钱么,计算机软件著作权登记收费吗
  13. Handler消息机制之深入理解Message.obtain()
  14. 关于智能名片小程序CRM系统,大家认为这种如何?
  15. oracle 百分比换算问题
  16. linux 深信服ssl_mac访问不了深信服的ssl vpn
  17. Linux中断原理、上半部和下半部、硬中断和软中断
  18. html网页制作,前端三剑客一
  19. C#打包文件夹成zip格式(包括文件夹和子文件夹下的所有文件)
  20. windows system info

热门文章

  1. java Exception 处理汇总
  2. Linux调度器 - deadline调度器
  3. 这不是我想要的Serverless
  4. 十一项全球最具权威的大数据资质认证
  5. PDF组件 Aspose.Pdf V17.6发布 | 新增单元格文档旋转功能
  6. 也谈谈Javascript中的几个怪异特性(上)
  7. jfinal启动正常,但是报错:oejw.WebAppContext:Failed startup
  8. 转:c++builder读写INI文件
  9. [RocketMQ]消息中间件—RocketMQ消息消费(一)
  10. JavaScript变量提升:函数提升要比变量提升更猛