zoukankan      html  css  js  c++  java
  • B/S模式实现批量打包apk

    界面流程

    界面例如以下:
    这里写图片描写叙述
    这是一个使用html编写的界面,界面分为两半。两个frame。左边为操作栏,右边为控制台输出。

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

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


    这里写图片描写叙述

    实现思路

    环境说明

    server使用的是apache server2.4.12,所以与浏览器的交互是使用cgi,关于cgi能够參考这里
    自己主动化的实现使用ant。关于ant能够參考这里

    开发工具:vs2013
    开发语言:html、javascript、C++
    系统:win7 x64

    浏览器与服务端的交互。

    服务端结构:
    这里写图片描写叙述

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

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

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

    // 获取选择的渠道列表
        function getChnnelList()
        {
            //getElementsByTagName:依据标签名获取元素集合
            //getElementById:依据id获取元素
            //getElementsByName:依据名称(name属性值)获取元素集合
            var checkboxes = document.getElementsByName('chnnel');      
            var len = checkboxes.length;
            var chnnelList = "";
            for(var i=0; i<len; ++i)
            {
                if(checkboxes[i].checked)
                {
                    chnnelList = chnnelList + checkboxes[i].value + " "; //把渠道id连接成字符串
                }
            }
            return chnnelList;
        }

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

    // 打包
        function requestPkg( data )
        {
            var img = document.getElementById("loadingImg");
            // 防止连续点击
            if('inline' == img.style.display){
                return
            }
    
            //显示loading
            showLoading();
    
            var xmlHttp = new XMLHttpRequest();
            // 1.提交方式(GET/POST)
            // 2.url
            // 3.是否异步
            xmlHttp.open( "POST", "http://localhost/cgi-bin/apkpkg.cgi", true );
            xmlHttp.overrideMimeType('text/plain; charset=gbk'); // 解决frame中文乱码问题
    
            // response handler
            xmlHttp.onreadystatechange = function () {
                if (xmlHttp.readyState == XMLHttpRequest.DONE) {
                    if (xmlHttp.status == 200) {
                        // 把返回数据显示在右边的frame
                        var doc = parent.right_frame.document;
    
                        //加入html文本
                        var html = doc.createElement("div");
                        html.className = "description";
                        html.innerHTML = xmlHttp.responseText;
                        doc.body.appendChild(html);
    
                        // 加入普通文本
                        //var txt=doc.createTextNode(xmlHttp.responseText)      
                        //doc.body.appendChild(txt)
    
                        //自己主动向下滚动
                        parent.right_frame.scrollBy(0, html.scrollHeight); 
                    } else if (xmlHttp.status == 400) {
                        console.log('There was an error 400');
                    } else {
                        console.log('something else other than 200 was returned');
                    }
    
                    //隐藏loading
                    hideLoading();
                }
            };
    
            // 发送请求
            xmlHttp.send( data );       
        }

    服务端处理流程例如以下:
    1.服务端接受到渠道id字符串后,对字符串进行切割并转换为整数,加入到chnnelList
    2.然后调用git pull(假设是svn则运行svn update)命令更新project。
    3.迭代chnnelList,依据渠道id运行不同的命令(ant能够把一系列操作简化成运行一个命令。事实上打包的过程。无非是对文件的一些操作。如删除、拷贝、移动、替换文件内容等,或者是运行一些命令,这些都能够通过ant实现,假设真遇到ant库提供的功能实现不了的需求,ant也提供了扩展的接口,详细可參考这里。能够的话也跟我说说吧。


    4.输出运行结果。

    //main.cpp
    #include <stdio.h>
    #include <iostream>
    #include "cmdlib.h"
    
    #include <vector>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <iterator>
    
    using namespace std;
    
    //常量
    class Constant{
    public:
        // project所在文件夹
        static const char* ProjectDir; //声明静态变量
    };
    // 静态变量的初始化
    const char* Constant::ProjectDir = "D:/AndroidDeveloper/workspace2/AntTest";
    
    
    // 依据渠道id运行不同的命令
    void exeCmd(int &id){
        switch (id)
        {
        //Debug
        case 1:
            cmd::exec_atdir(Constant::ProjectDir, "ant buildDebug", true);
            break;
        //小米
        case 2:
            cmd::exec_atdir(Constant::ProjectDir, "ant buildXiaoMi", true);
            break;
        //360 
        case 3:
    
            break;
        //安智 
        case 4:
    
            break;
        //应用汇 
        case 5:
    
            break;
        //中国移动 
        case 6:
    
            break;
        //中国联通 
        case 7:
    
            break;
        //中国电信 
        case 8:
    
            break;
        //九游
        case 9:
    
            break;
        }
    }
    
    void main(){
        cout<<"Context-type:text/html; charset=UTF-8 
    
    ";
        cout<<"<html>";
        cout<<"<body>";
    
        // 获取提交的參数
        char params[256] = { 0 };
        gets_s(params);//获取输入
        cout << "<p>params=" << params << "</p>";
    
        vector<string> chnnelStrList;
        istringstream iss(params);
        // 对字符串进行切割,并复制到渠道列表
        copy(istream_iterator<string>(iss),             // 開始位置
            istream_iterator<string>(),                 // 结束位置
            back_inserter<vector<string>>(chnnelStrList)); // push_back到vector
    
        // 把字符串转换成整数
        vector<int> chnnelLlist;
        int chnnel = 0;
        for_each(chnnelStrList.begin(), chnnelStrList.end(), [&chnnel, &chnnelLlist](string & str){
            chnnel = atoi(str.c_str());
            if (chnnel != 0)
            {
                chnnelLlist.push_back(chnnel);
            }
        });
    
        // 首先更新project
        // svn update / git pull
        cmd::exec_atdir(Constant::ProjectDir, "git pull", false);
    
        // 依据id运行相应的命令
        for_each(chnnelLlist.begin(), chnnelLlist.end(), [](int & id){
            exeCmd(id);
        });
    
        cout<<"</body>";
        cout<<"</html>";
    }
    // cmdlib.h
    #ifndef __CMDLIB_H__
    #define __CMDLIB_H__
    
    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    
    using namespace std;
    
    namespace cmd{
    
        // 运行命令并输出
        bool exec_output(const char* cmd){
            // 运行命令,并打印输出
            FILE* pipe = _popen(cmd, "r"); // 第一个參数是指令字符串。第二个參数是模式(r:读,w:写)
            // _popen函数用于运行一条指令并把结果输出到内存中的文件对象
    
            if (!pipe)
            {
                return false;
            }
    
            cout << "<p>";
            // 把运行结果输出到网页
            char ch = 0;
            while (!feof(pipe)){
                ch = fgetc(pipe);
                // 把'
    '换行符换成网页中的换行符<br />
                if (ch == '
    ')
                {
                    cout<<"<br />";
                }
                else{
                    putchar(ch);
                }
            }
            cout << "</p>";
            return true;
        }
    
        // 在指定文件夹下运行一个命令
        // dir:文件夹路径
        // cmd:命令
        // is_out:是否输出运行结果
        void exec_atdir(const char* dir, const char* cmd, bool is_out = false){
            char buff[1024] = { 0 };
    
    #if _WIN32
            sprintf_s(buff, "cd /d %s & %s", dir, cmd);
    #else
            sprintf_s(buff, "cd %s & %s", dir, cmd);
    #endif
            if (is_out)
            {
                exec_output(buff);
            }
            else{
                system(buff);
            }
        }
    
    };
    
    #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

  • 相关阅读:
    设计说明书 转
    软件项目详细设计文档规范
    记帐凭证怎样分类?
    Delphi中WideString类型如何转化成String类型
    更靠谱的横竖屏检测方法
    超级小的web手势库AlloyFinger发布
    狗日的rem
    js 面试的坑
    【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验
    移动端 关于 键盘将input 框 顶上去的解决思路---个人见解
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7363109.html
Copyright © 2011-2022 走看看