要实现java一键生成渠道包功能,事先我们需要做好准备工作,大概有以下3点
1.准备好所以需要生成的渠道号放在excel文档中
2.需要下载两个jar包,commons-compress-1.16.1.jar和 jxl.jar
3.得准备你需要生成渠道包的apk,也就是说你需要在你的Android开发工具中先打
一个包,然后代码会根据这个包生成不同的渠道包
注:这些资料我都将在文章结尾给出,好废话不多说,现在开始功能的实现
一.首先你的电脑上得有java开发工具,我用的是IntelliJ IDEA 开发工具。
1.新建一个java项目PackingTools,把commons-compress-1.16.1.jar和 jxl.jar这个两个jar包复制到libs文件中并添加依赖。
2.新建一个ApkChannel类,这个类需要实现两个方法
1.遍历读取excel文档中事先准备好的渠道号
try {
//ckjr.xls 是所有要打包的平台渠道名excel表格
Workbook book = Workbook.getWorkbook(new FileInputStream(new File("F:/ckjr.xls")));
Sheet sheet = book.getSheet(0);
for (int i = 1; i < sheet.getRows(); i++) {
String contents = sheet.getCell(1, i).getContents();
if (contents != null && !"".equals(contents.trim())) {
mQueue.offer(contents);
}
}
book.close();
} catch (Exception e) {
e.printStackTrace();
}
File dfile = new File("F:/渠道打包/" + appName);
if(!dfile.exists())
dfile.mkdirs();
String path = dfile.getPath();
int index = 0;
while(index++<15) {
new Thread(new Runnable() {
@Override
public void run() {
new ApkChannel02().startCopy(path);
}
}).start();
}
2.把渠道号通过代码的形式注入到apk中
private void startCopy(String outPath) {
try {
String channel;
while((channel=mQueue.poll(1, TimeUnit.SECONDS))!=null) {
File file = new File(apkPath);
FileOutputStream fos = new FileOutputStream(outPath+"/"+appName+"_" + channel +versionName);
ZipFile zipFile = new ZipFile(file);
ZipArchiveOutputStream zos = new ZipArchiveOutputStream(fos);
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while(entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
zos.putArchiveEntry(entry);
// zos.putArchiveEntry(new ZipArchiveEntry(entry.getName()));
int length;
byte[] buffer = new byte[1024];
InputStream is = zipFile.getInputStream(entry);
while((length=is.read(buffer))!=-1) {
zos.write(buffer, 0, length);
}
is.close();
buffer = null;
}
zos.putArchiveEntry(new ZipArchiveEntry("META-INF/channel_" + channel));
zos.closeArchiveEntry();
zos.close();
System.out.println("剩余" + mQueue.size());
}
if(mQueue.size()==0) {
openOutputFile();
// System.out.println("done");
}
} catch (Exception e) {
e.printStackTrace();
}
}
完整代码如下:
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import jxl.Sheet;
import jxl.Workbook;
/**
*@desc java实现一键打包工具
*@author zhengjun
*@created at 2018/5/4 16:59
*/
public class ApkChannel{
private static final String versionName = "_3.7.8.apk"; //当前打包的版本号
private static final String appName = "ckjr"; //apk名称,根据你的项目自己命名
//事先准备好的打包apk,根据这个apk生成不同平台的apk,放在事先在F盘建好的 "渠道打包" 这个文件夹中
private static final String apkPath = "F:/渠道打包/"+appName+versionName;
static LinkedBlockingQueue<String> mQueue = new LinkedBlockingQueue<>(); //存储从excel中读取到的所有渠道号
public static void main(String[] args) {
try {
//ckjr.xls 是所有要打包的平台渠道名
Workbook book = Workbook.getWorkbook(new FileInputStream(new File("F:/ckjr.xls")));
Sheet sheet = book.getSheet(0);
//这里循环从1开始是因为我的excel文档中空了一行没写内容
for (int i = 1; i < sheet.getRows(); i++) {
String contents = sheet.getCell(1, i).getContents();
if (contents != null && !"".equals(contents.trim())) {
mQueue.offer(contents);
}
}
book.close();
} catch (Exception e) {
e.printStackTrace();
}
File dfile = new File("F:/渠道打包/" + appName);
if(!dfile.exists())
dfile.mkdirs();
String path = dfile.getPath();
int index = 0;
while(index++<15) {
new Thread(new Runnable() {
@Override
public void run() {
new ApkChannel().startCopy(path);
}
}).start();
}
}
//开始打包
private void startCopy(String outPath) {
try {
String channel;
while((channel=mQueue.poll(1, TimeUnit.SECONDS))!=null) {
File file = new File(apkPath);
FileOutputStream fos = new FileOutputStream(outPath+"/"+appName+"_" + channel +versionName);
ZipFile zipFile = new ZipFile(file);
ZipArchiveOutputStream zos = new ZipArchiveOutputStream(fos);
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while(entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
zos.putArchiveEntry(entry);
int length;
byte[] buffer = new byte[1024];
InputStream is = zipFile.getInputStream(entry);
while((length=is.read(buffer))!=-1) {
zos.write(buffer, 0, length);
}
is.close();
buffer = null;
}
zos.putArchiveEntry(new ZipArchiveEntry("META-INF/channel_" + channel));
zos.closeArchiveEntry();
zos.close();
System.out.println("剩余" + mQueue.size());
}
if(mQueue.size()==0) {
openOutputFile();
}
} catch (Exception e) {
e.printStackTrace();
}
}
boolean opened = false;
//打包完成之后 自动打开输出路径
private void openOutputFile() {
synchronized (this) {
if(opened) {
return;
}
opened = true;
}
String[] cmd = new String[5];
cmd[0] = "cmd";
cmd[1] = "/c";
cmd[2] = "start";
cmd[3] = " ";
cmd[4] = "F:/渠道打包";
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后运行main方法即可
二. 还需要在你的Android项目中进行一些处理
1.获取包的渠道号
/**
* 获取渠道号
*
* @param context
* @return
*/
public static String getChannel(Context context) {
if (context == null)
return "";
if (!TextUtils.isEmpty(channel)) {
return channel;
}
try {
ZipFile zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
Enumeration entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String entryName = entry.getName();
//META-INF/channel_这个标识需要跟你打包时候注入渠道号时的一致
if (entryName.contains("META-INF/channel_")) {
channel = entryName.replace("META-INF/channel_", "");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (TextUtils.isEmpty(channel)){
channel = "ckjr_hos";
}
return channel;
}
2.在application中进行umeng初始化的时候注入进去
//友盟初始化,第一个参数为友盟的appkey,第二个参数为渠道号
UMConfigure.init(this, AppConfig.UMENAPPKEY
, getChannel(getApplicationContext()), UMConfigure.DEVICE_TYPE_PHONE, "");
最后附上源码的链接地址:https://download.csdn.net/download/qq_20489601/10692821