android-多渠道自动打包之一秒五包

来源:互联网 发布:软件企业认定有效期 编辑:程序博客网 时间:2024/05/17 20:02

现在的渠道越来越多了,然后在打包的这个问题上要暂用非常多的时间,所以我也总结出了一篇关于自动打包的博文http://blog.csdn.net/a641832648/article/details/52163493

但是,apktool并不是万能的,有时候会遇到一些莫名其妙的错误,然后实在是没有办法了,赶紧再去搜一搜有没有什么比较吊的多渠道自动打包方式。一搜还真的有!是美团的一个多渠道自动打包方式。具体的地址我找不到在哪了。。

这种打包方式我暂且称之为一秒五包。。。

我们知道,apk解压出来的话里面会有一个META-INF文件夹

然后一秒五包的打包方式就是在这个文件夹里面增加一个空的文件夹。(至于为什么要多渠道打包可以在META-INF中增加一个空的文件而不影响apk,或者这个打包原理的话可以看一下apk的编译过程跟原理。)

当然了,在这个META-INF文件夹中创建一个空的文件夹后,肯定要获取,这个空文件夹,然后根据文件夹的文件名来唯一标识一个渠道。如:

要获取360的渠道。则在META-INF文件夹增加一个BOKE_360,或者可以唯一标识的一个空文件:


然后在java代码中获取META-INF文件夹的这个空文件的文件名名就ok啦!!

public static String getChannel(Activity activity)  {    if (channel != null) {      return channel;    }    String start_flag = "META-INF/BOKE_";    ApplicationInfo appinfo = activity.getApplicationInfo();    String sourceDir = appinfo.sourceDir;    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.contains("META-INF/BOKE_")) {//获取BOKE_XXX          channel = entryName.replace("META-INF/BOKE_", "");//截取BOKE_从而获取渠道Id          break;        }      }    } catch (IOException e) {      e.printStackTrace();    }    finally{      if (zipfile != null) {        try {          zipfile.close();        } catch (IOException e) {          e.printStackTrace();        }      }    }     return channel;  }
然后在适当的时候调用这个代码就可以获取到渠道号了!

然后手动的话根本不可能。。要自动打包的话,首先我们知道了这个获取的方式。,要实现自动打包的话无非就是解压apk,然后获取往apk的META-INF文件夹中添加空文件夹。知道了这个实现过程,就可以写一个批处理的jar包来来实现多渠道打包。。

以下是我写的一个jar包:

public class SplitFastApk {    ArrayList<String> channel = new ArrayList<String>();    //渠道号  String curPath;//当前文件夹路径    String apkPath;  //apk路径  String endApkName;//打包后的apk名称int startNumber;//打包的起始编号private String papau = "papau_";//命名public SplitFastApk(String apkName) {// 构造函数接受参数    this.curPath = new File("").getAbsolutePath();    this.apkPath = apkName;    //传入apk名称}    public void mySplit() {    getCannelFile();// 获得自定义的渠道号    modifyXudao();// 解包 - 打包 - 签名    }    /**   * 获得渠道号   */    private void getCannelFile() {    File f = new File("channel.txt");// 读取当前文件夹下的channel.txt    if (f.exists() && f.isFile()) {    BufferedReader br = null;    FileReader fr = null;    try {    fr = new FileReader(f);    br = new BufferedReader(fr);    String line = null;    while ((line = br.readLine()) != null) {    String[] array = line.split("-");// 这里是Tab分割   int start = Integer.parseInt(array[0]);   int end = Integer.parseInt(array[1]);for (int i = start; i <= end; i++) {//获取渠道号channel.add(""+i);  }this.endApkName = array[2];//apk名字this.startNumber = Integer.parseInt(array[3]);//包的起始编号}    } catch (Exception e) {    e.printStackTrace();    } finally {    try {    if (fr != null) {    fr.close();    }    if (br != null) {    br.close();    }    } catch (IOException e) {    e.printStackTrace();    }    }    System.out.println("==INFO 1.==获取渠道成功,一共有" + channel.size()    + "个渠道======");    System.out.println("==INFO 1.==获取名称成功" + this.endApkName    + "个渠道======");    System.out.println("==INFO 1.==编号成功,编号起始为" + this.startNumber    + "======");    } else {    System.out.println("==ERROR==channel.txt文件不存在,请添加渠道文件======");    System.exit(0);}    }    /**   * apktool解压apk,替换渠道值   *    * @throws Exception   */    private void modifyXudao() {    // 创建生成结果的目录    File f = new File("apk");    if (!f.exists()) {    f.mkdir();    }  new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < channel.size(); i++) {    ZipFile targetApk = null;//目标apkZipOutputStream originalApk = null;//母包apktry {    String id = channel.get(i);    System.out.println("==INFO 2. == 正在生成包: " + id    + " ======");    String originalStr = curPath+"/apk/"+ endApkName + "" + startNumber + ".apk"; targetApk = new ZipFile(apkPath);originalApk = new ZipOutputStream(new FileOutputStream(originalStr));// first, copy contents from existing warEnumeration<? extends ZipEntry> entries = targetApk.getEntries();while (entries.hasMoreElements()) {ZipEntry e = entries.nextElement();originalApk.putNextEntry(e);if (!e.isDirectory()) {copy(targetApk.getInputStream(e), originalApk);}originalApk.closeEntry();}ZipEntry e = new ZipEntry("META-INF/"+papau+id);//写入一个名为papau_XXX的空文件originalApk.putNextEntry(e);originalApk.closeEntry();System.out.println("==INFO 3 == 正在生成包: " + id    + "成功 ======");} catch (Exception error) {    error.printStackTrace();  System.out.println("打包错误");} finally {    try {targetApk.close();originalApk.close();} catch (IOException e) {e.printStackTrace();System.out.println("打包错误");}}  startNumber++;}    System.out.println("==INFO 5 == 完成 ======");  }}).start();  }    // 4MB bufferprivate static final byte[] BUFFER = new byte[4096 * 1024];/** * copy input to output stream - available in several StreamUtils or Streams classes  */    public static void copy(InputStream input, OutputStream output) throws IOException {int bytesRead;while ((bytesRead = input.read(BUFFER))!= -1) {output.write(BUFFER, 0, bytesRead);}}} 

我前面放的那个博文跟这个有点像,就是方式改了一下

ps:要把很多个jar包打包成一个jar包的话可以先把jar包解压成class文件,然后cmd命令行进入目录输入jar cvf XXXX.jar *就会融合所有的jar包

0 0
原创粉丝点击