界面流程

界面例如以下:



这是一个使用html编写的界面,界面分为两半。两个frame。左边为操作栏,右边为控制台输出。

打包流程:

选择须要打包的渠道后,点击打包,等待server打包,并把日志输出到右边的frame。

打包完毕后。点击”点击打开下载界面”链接。跳转到下载界面。

实现思路

环境说明

server使用的是apache server2.4.12,所以与浏览器的交互是使用cgi,关于cgi能够參考这里

自己主动化的实现使用ant。关于ant能够參考这里

开发工具:vs2013

开发语言:html、javascript、C++

系统:win7 x64

浏览器与服务端的交互。

服务端结构:

在主界面左边的frame中有一个渠道列表,每一个渠道相应一个id。

  1. <fieldset align="left" >
  2. <legend>渠道列表:</legend>
  3. <label class="labelChnnel">Debug<input class="btnChnnel" name="chnnel" type="checkbox" value="1" /></label>
  4. <label class="labelChnnel">小米<input class="btnChnnel" name="chnnel" type="checkbox" value="2" /></label>
  5. <label class="labelChnnel">360<input class="btnChnnel" name="chnnel" type="checkbox" value="3" /></label>
  6. <label class="labelChnnel">安智<input class="btnChnnel" name="chnnel" type="checkbox" value="4" /></label>
  7. <label class="labelChnnel">应用汇<input class="btnChnnel" name="chnnel" type="checkbox" value="5" /></label>
  8. <label class="labelChnnel">中国移动<input class="btnChnnel" name="chnnel" type="checkbox" value="6" /></label>
  9. <label class="labelChnnel">中国联通<input class="btnChnnel" name="chnnel" type="checkbox" value="7" /></label>
  10. <label class="labelChnnel">中国电信<input class="btnChnnel" name="chnnel" type="checkbox" value="8" /></label>
  11. <label class="labelChnnel">九游<input class="btnChnnel" name="chnnel" type="checkbox" value="9" /></label>
  12. </fieldset>

当点击打包的时候,会先获取当前选择的全部的渠道id并连接成一个字符串。

  1. // 获取选择的渠道列表
  2. function getChnnelList()
  3. {
  4. //getElementsByTagName:依据标签名获取元素集合
  5. //getElementById:依据id获取元素
  6. //getElementsByName:依据名称(name属性值)获取元素集合
  7. var checkboxes = document.getElementsByName('chnnel');
  8. var len = checkboxes.length;
  9. var chnnelList = "";
  10. for(var i=0; i<len; ++i)
  11. {
  12. if(checkboxes[i].checked)
  13. {
  14. chnnelList = chnnelList + checkboxes[i].value + " "; //把渠道id连接成字符串
  15. }
  16. }
  17. return chnnelList;
  18. }

接着调用requestPkg方法并把渠道id字符串传入,该方法会发送一个异步请求到服务端。并把server返回的数据显示在右边的frame中。

  1. // 打包
  2. function requestPkg( data )
  3. {
  4. var img = document.getElementById("loadingImg");
  5. // 防止连续点击
  6. if('inline' == img.style.display){
  7. return
  8. }
  9. //显示loading
  10. showLoading();
  11. var xmlHttp = new XMLHttpRequest();
  12. // 1.提交方式(GET/POST)
  13. // 2.url
  14. // 3.是否异步
  15. xmlHttp.open( "POST", "http://localhost/cgi-bin/apkpkg.cgi", true );
  16. xmlHttp.overrideMimeType('text/plain; charset=gbk'); // 解决frame中文乱码问题
  17. // response handler
  18. xmlHttp.onreadystatechange = function () {
  19. if (xmlHttp.readyState == XMLHttpRequest.DONE) {
  20. if (xmlHttp.status == 200) {
  21. // 把返回数据显示在右边的frame
  22. var doc = parent.right_frame.document;
  23. //加入html文本
  24. var html = doc.createElement("div");
  25. html.className = "description";
  26. html.innerHTML = xmlHttp.responseText;
  27. doc.body.appendChild(html);
  28. // 加入普通文本
  29. //var txt=doc.createTextNode(xmlHttp.responseText)
  30. //doc.body.appendChild(txt)
  31. //自己主动向下滚动
  32. parent.right_frame.scrollBy(0, html.scrollHeight);
  33. } else if (xmlHttp.status == 400) {
  34. console.log('There was an error 400');
  35. } else {
  36. console.log('something else other than 200 was returned');
  37. }
  38. //隐藏loading
  39. hideLoading();
  40. }
  41. };
  42. // 发送请求
  43. xmlHttp.send( data );
  44. }

服务端处理流程例如以下:

1.服务端接受到渠道id字符串后,对字符串进行切割并转换为整数,加入到chnnelList

2.然后调用git pull(假设是svn则运行svn update)命令更新project。

3.迭代chnnelList,依据渠道id运行不同的命令(ant能够把一系列操作简化成运行一个命令。事实上打包的过程。无非是对文件的一些操作。如删除、拷贝、移动、替换文件内容等,或者是运行一些命令,这些都能够通过ant实现,假设真遇到ant库提供的功能实现不了的需求,ant也提供了扩展的接口,详细可參考这里。能够的话也跟我说说吧。



4.输出运行结果。

  1. //main.cpp
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include "cmdlib.h"
  5. #include <vector>
  6. #include <string>
  7. #include <sstream>
  8. #include <algorithm>
  9. #include <iterator>
  10. using namespace std;
  11. //常量
  12. class Constant{
  13. public:
  14. // project所在文件夹
  15. static const char* ProjectDir; //声明静态变量
  16. };
  17. // 静态变量的初始化
  18. const char* Constant::ProjectDir = "D:/AndroidDeveloper/workspace2/AntTest";
  19. // 依据渠道id运行不同的命令
  20. void exeCmd(int &id){
  21. switch (id)
  22. {
  23. //Debug
  24. case 1:
  25. cmd::exec_atdir(Constant::ProjectDir, "ant buildDebug", true);
  26. break;
  27. //小米
  28. case 2:
  29. cmd::exec_atdir(Constant::ProjectDir, "ant buildXiaoMi", true);
  30. break;
  31. //360
  32. case 3:
  33. break;
  34. //安智
  35. case 4:
  36. break;
  37. //应用汇
  38. case 5:
  39. break;
  40. //中国移动
  41. case 6:
  42. break;
  43. //中国联通
  44. case 7:
  45. break;
  46. //中国电信
  47. case 8:
  48. break;
  49. //九游
  50. case 9:
  51. break;
  52. }
  53. }
  54. void main(){
  55. cout<<"Context-type:text/html; charset=UTF-8 \n\n";
  56. cout<<"<html>";
  57. cout<<"<body>";
  58. // 获取提交的參数
  59. char params[256] = { 0 };
  60. gets_s(params);//获取输入
  61. cout << "<p>params=" << params << "</p>";
  62. vector<string> chnnelStrList;
  63. istringstream iss(params);
  64. // 对字符串进行切割,并复制到渠道列表
  65. copy(istream_iterator<string>(iss), // 開始位置
  66. istream_iterator<string>(), // 结束位置
  67. back_inserter<vector<string>>(chnnelStrList)); // push_back到vector
  68. // 把字符串转换成整数
  69. vector<int> chnnelLlist;
  70. int chnnel = 0;
  71. for_each(chnnelStrList.begin(), chnnelStrList.end(), [&chnnel, &chnnelLlist](string & str){
  72. chnnel = atoi(str.c_str());
  73. if (chnnel != 0)
  74. {
  75. chnnelLlist.push_back(chnnel);
  76. }
  77. });
  78. // 首先更新project
  79. // svn update / git pull
  80. cmd::exec_atdir(Constant::ProjectDir, "git pull", false);
  81. // 依据id运行相应的命令
  82. for_each(chnnelLlist.begin(), chnnelLlist.end(), [](int & id){
  83. exeCmd(id);
  84. });
  85. cout<<"</body>";
  86. cout<<"</html>";
  87. }
  1. // cmdlib.h
  2. #ifndef __CMDLIB_H__
  3. #define __CMDLIB_H__
  4. #include <iostream>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. using namespace std;
  8. namespace cmd{
  9. // 运行命令并输出
  10. bool exec_output(const char* cmd){
  11. // 运行命令,并打印输出
  12. FILE* pipe = _popen(cmd, "r"); // 第一个參数是指令字符串。第二个參数是模式(r:读,w:写)
  13. // _popen函数用于运行一条指令并把结果输出到内存中的文件对象
  14. if (!pipe)
  15. {
  16. return false;
  17. }
  18. cout << "<p>";
  19. // 把运行结果输出到网页
  20. char ch = 0;
  21. while (!feof(pipe)){
  22. ch = fgetc(pipe);
  23. // 把'\n'换行符换成网页中的换行符<br />
  24. if (ch == '\n')
  25. {
  26. cout<<"<br />";
  27. }
  28. else{
  29. putchar(ch);
  30. }
  31. }
  32. cout << "</p>";
  33. return true;
  34. }
  35. // 在指定文件夹下运行一个命令
  36. // dir:文件夹路径
  37. // cmd:命令
  38. // is_out:是否输出运行结果
  39. void exec_atdir(const char* dir, const char* cmd, bool is_out = false){
  40. char buff[1024] = { 0 };
  41. #if _WIN32
  42. sprintf_s(buff, "cd /d %s & %s", dir, cmd);
  43. #else
  44. sprintf_s(buff, "cd %s & %s", dir, cmd);
  45. #endif
  46. if (is_out)
  47. {
  48. exec_output(buff);
  49. }
  50. else{
  51. system(buff);
  52. }
  53. }
  54. };
  55. #endif

在Apache Server安装文件夹下有一个htdocs文件夹,是站点的根文件夹。我在这里新建了一个apk文件夹。用于存放所以自己主动生成的apk。通过http://localhost/apk(这里的localhost指server的ip。由于我在本地測试所以使用localhost)能够在浏览器訪问该文件夹。

通过ant命令生成的apk最后会被移动到该文件夹下。

最后,渠道包生成完毕后,点击链接。浏览器跳转到渠道包列表网页下载渠道包。

相关文章

1.Ant开发总结

2.CGI编程

项目地址:https://coding.net/u/linchaolong/p/BSBatchPkgTool/git

B/S模式实现批量打包apk的更多相关文章

  1. 整理的Unity导出安卓工程利用ANT进行多渠道批量打包APK

    Unity导出的安卓工程利用ant进行多渠道循环批量打包 一:设置JAVA环境变量 做android开发的配置这个是基础. win7 下配置java环境变量,下面是链接 http://www.cnbl ...

  2. Android 自动编译、打包生成apk文件 4 - 多渠道批量打包

    相关文章列表: < Android 自动编译.打包生成apk文件 1 - 命令行方式> < Android 自动编译.打包生成apk文件 2 - 使用原生Ant方式 > < ...

  3. Android批量打包-如何一秒内打完几百个apk渠道包

    在国内Android常用渠道可能多达几十个,如: 谷歌市场.腾讯应用宝.百度手机助手.91手机商城.360应用平台.豌豆荚.安卓市场.小米.魅族商店.oppo手机.联想乐商.中兴汇天地.华为.安智.应 ...

  4. Unity3D研究院之脚本批量打包渠道包研究

    原地址:http://www.xuanyusong.com/archives/2418#comments 最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的 ...

  5. Unity3D脚本批量打包渠道包

    最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的机器,可能还有不同的渠道包,不同渠道可能用的SDK都不一样,这一切的一切都表明你的代码无法做到自适应的,除 ...

  6. Android Studio 多个编译环境配置 多渠道打包 APK输出配置

    看完这篇你学到什么: 熟悉gradle的构建配置 熟悉代码构建环境的目录结构,你知道的不仅仅是只有src/main 开发.生成环境等等环境可以任意切换打包 多渠道打包 APK输出文件配置 需求 一般我 ...

  7. Unity自动打包 apk

    1.流程 Unity打包 apk,会把Unity安装目录下的默认 AndroidManifest.Xml 文件覆盖到apk中去,同时还会拷贝该文件所在目录下的其它默认设置文件,如 res 和 asse ...

  8. 在Android开发中使用Ant 三:批量打包

    批量打包最常用到的地方是进行产品推广时,为每个渠道打一个包.上一篇随笔中,介绍了怎样进行一次完整的打包,批量打包只要在此基础上做一次循环即可. 在打包之前要做两个准备工作,一个是读取渠道,一个是修改存 ...

  9. Unity自动打包Apk

    unity打包apk相对来说比较容易,相信出过的人都明白,出包过程,没有大的难度,一步一操作,一步一等待,繁琐耗时,不懂的人又代替不了.这时候需求就来了,如何简单的一键打包搞定,这个就稍微有点难度,当 ...

随机推荐

  1. 使用JPush(极光推送)实现远程通知

    使用JPush(极光推送)实现远程通知 远程推送是APP 必备的功能, 现在第三方的 SDK 已经做的非常完备了, 在 iOS10.0出来之后, 极光推送也及时更新了他的 SDK, 今天小试了一下效果 ...

  2. Linux下golang开发环境搭建

    对于golang开发来说,Windows下可以用vscode或者liteide都不错,但是Linux下的开发也就只有vim了,所以怎么搞笑的利用vim进行golang开发呢? 参考官方推荐的一个插件: ...

  3. Python(一)之Python概述

    前言:最近学习Python基础,网上找了视频教程,本篇记录下Python概况,学习环境Python2.6. 学习Python首先得会获取Python自带的帮助信息,下面几个实用的内置函数,不管是工作或 ...

  4. Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.

    System.Data.ConstraintException: Failed to enable constraints. One or more rows contain values viola ...

  5. 【UE4】VR模式下全屏(去掉两侧的黑边)

    1.下载UE4源码,用Visual Studio打开源码找到指定文件,修改代码后重新编译得到一个新的UE4编辑器 2.将游戏项目在新的UE4中打开,重新编译. 参考: https://caedmom. ...

  6. 从Unauthorized 401错误学习Spring Boot的Actuator

    之前用Spring Boot都是别人搭好的框架,然后自己在里面写就行了.对原理.细节上都怎么涉及,毕竟需求都做不完.但是昨天一个访问RESTful接口的401问题搞了我2个小时.网上找的很多用: ma ...

  7. STM32 ACM Linux 驱动添加

    kernel 内驱动添加如下: x Symbol: USB_ACM [=y] x x Type : tristate x x Prompt: USB Modem (CDC ACM) support x ...

  8. [Issue]git做rebase时,弹出编辑器为nano,不会使用

    今天在做一个branch的rebase, 执行git rebase -i master的时候,自动弹出了nano 编译器,捣鼓了很久,还是不会编译,保存退出,执行Ctrl+X就自动结束了,查了下,需要 ...

  9. Extjs4.2 Tree使用技巧小结demo

    本案例使用了Ext.Tree.Panel的如下知识点: 1.刷新.重新加载Tree,定位到上次的节点位置 2.Tree的右键操作 3.Extjs4.x Tree获取当前选中的节点 4.新增.修改.删除 ...

  10. Kryonet client disconnects after send a packet to server (java)

    http://stackoverflow.com/questions/25934876/kryonet-client-disconnects-after-send-a-packet-to-server ...