因为公司的APP需要向多平台发布,并且同一份APP源码会切换厂商发多种版本的APP。然而,虽然我有做厂商的区分文件,但每次源码切换厂商总是耗时,而且手动切换(进行文本覆盖),总有时候会有些漏的和错的。特别向AndroidManifest.xml文件,大部分的内容是相同的,但因为有接入第三方的sdk,有些差异的地方需要手动改,多版本维护,会存在错漏。
为此,为了减轻工作量,特意做了个快速替换厂商文件,及部署APK的脚本。

先说下我的思路,gradle命令中

gradle assembleDebug //打包Debug包
gradle assembleRelease //打包Release包

可以进行APK的打包,当然需要部署gradle的环境。
gradle的命令需要jdk8的版本进行支持。
我当前的gradle版本是gradle-3.3
http://download.csdn.net/download/feiniyan4944/10178513

然后通过jarsigner命令可以对APK进行签名

jarsigner -digestalg SHA1 -sigalg MD5withRSA -keystore 签名文件 -storepass
密码 -signedjar 打包后的APK路径 未打包的APK路径 别名

又因为上面的命令都是在cmd跑的,然后脚本我选择了bat脚本处理。

剩下的就是对存在差异数据厂商的文件进行处理。但用bat脚本我不会处理这么大量的数据,因为我是做java开发的,于是选择java进行处理了。

先附上效果图一张


好了附上我的bat源码
appbuild.bat

:: 不显示后续命令行及当前命令行
@echo off::选择厂商
set platform=0
::获取当前脚本的路径
set bulidPath=%cd%
::取得上一级工程目录
cd..
set iremotePath=%cd%
::差异厂商的apk存放路径
set folderName=jwzh
:: 版本号
set version=
goto ChoosePlatform
:ChoosePlatform
@echo *******************************
@echo.
@echo          版本打包
@echo.
@echo *******************************
@echo.
@echo.
@echo 请选择厂家版本
@echo 1.百度 baidu
@echo 2.谷歌 google
:: /c按键列表 /m提示内容 /d默认选择 /t等待秒数   /d 必须和 /t同时出现
choice /c:123 /m:"" /d:1 /t:20
if %errorlevel%==1 goto baidu
if %errorlevel%==2 goto google:baidu
set platform=1
set folderName=baidu
@echo 百度版本
goto platformReplace:google
set platform=2
set folderName=google
@echo 谷歌版本
goto platformReplace::java代码厂商文件替换
:platformReplace
@echo 正在编译厂商处理文件...
cd %bulidPath%\java
javac -cp AXmlResourceParser.jar;jdom-2.0.2.jar PlatformChange.java
@echo 正在进行厂商文件处理...
@echo.
java -cp AXmlResourceParser.jar;jdom-2.0.2.jar; PlatformChange %platform% %iremotePath%@echo.::获取配置文件的版本号,这里的配置文件不是apk本身的文件,是做的厂商数据存储文件
::开启变量延迟
setlocal enabledelayedexpansion
@echo 读取版本号
set platformPath=%iremotePath%\app\platformres\%folderName%\platform.xml
@echo %platformPath%
for /f "delims=" %%i in (%platformPath%) do (echo "%%i"|findstr "version" >nulif !errorlevel! equ 0 (set "version=%%i"goto version_goto)
)
goto assemble
:version_goto
::关闭变量延迟
setlocal disabledelayedexpansion
for /f tokens^=2^ delims^=^" %%a in ("%version%") do set "version=%%a"
echo 当前版本号为:%version%
@echo.:assemble
::打包前清空其文件夹下所有文件,防止打包不成功签名成旧版本的apk
del /q /s %iremotePath%\app\build\outputs\apk
set assemble=
cd %iremotePath%
@echo 请选择打包类型
@echo 1.Debug
@echo 2.Release
@echo 3.取消打包
choice /c 123 /m "" /d 2 /t 20
if %errorlevel%==1 goto debug
if %errorlevel%==2 goto release
if %errorlevel%==3 goto end::gradle需要jdk8支持
:debug
@echo.
set assemble=1
@echo 开始进行debug打包
CALL %bulidPath%\assemble.bat
md %bulidPath%\apk\%folderName%
copy %iremotePath%\app\build\outputs\apk\debug\app-debug.apk %bulidPath%\apk\%folderName%\app_Debug_%folderName%_%version%.apk
@echo.
@echo debug版本app_Debug_%folderName%_%version%.apk打包完毕
goto end:release
@echo.
set assemble=2
@echo 开始进行release打包
CALL %bulidPath%\assemble.bat
@echo.
@echo release版本打包完毕
goto key::签名
:key
@echo.
md %bulidPath%\apk\%folderName%
::签名后的apk地址
set apkname=%bulidPath%\apk\%folderName%\app_%folderName%_%version%.apk
::未签名APK路径
set apkSigned=%iremotePath%\app\build\outputs\release\apk\app-release-unsigned.apk
::密钥
set key=%iremotePath%\app\AndroidappKey.jks
::密码
set password=123456
::别名
set keystore=appecho 签名信息
echo 签名后的apk地址:%apkname%
echo 未签名APK路径:%apkSigned%
echo 密钥文件地址:%key%
echo 密钥密码:%password%
echo 别名:%keystore%
echo.
echo 正在进行apk签名...
::签名
::jarsigner打包需要jdk7支持
::jarsigner -digestalg SHA1 -sigalg MD5withRSA -keystore [你的keystore] -storepass [keystore的密码] -signedjar [签名后的apk] [未签名的apk] [keystore的别名]
jarsigner -digestalg SHA1 -sigalg MD5withRSA -keystore %key% -storepass %password% -signedjar %apkname%  %apkSigned% %keystore%
echo.
echo 签名完成
goto end:end
echo.
if %platform%==1 echo 百度版本打包完毕
if %platform%==2 echo 谷歌版本打包完毕
echo.
pause:: 冒号后紧跟一个非字母数字的一个特殊符号,goto无法识别的标号,可以起到注释作用
:: UTF-8格式会出现英文乱码,要ANSI 格式

assemble.bat

@echo off
if "%assemble%"=="1" goto debug
if "%assemble%"=="2" goto release:debug
gradle assembleDebug:release
gradle assembleRelease

处理厂商文件的java源码
PlatformChange.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
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;
import java.io.Writer;
import java.util.List;
import java.util.Scanner;import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.xml.sax.InputSource;public class PlatformChange {static String platform;//厂商static String iremotePath;//工程地址static String version;//版本static String platforPackage;//厂商包名static String jpushkey;//推送的appkeystatic String folderName;public static void main(String[] args) {platform = args[0];//厂商iremotePath = args[1];//工程地址System.out.println("厂商" + platform);System.out.println("工程地址:" + iremotePath);System.out.println("读取版本信息文件");readPlatformXml();System.out.println("处理AndroidManifest版本信息");changeAndroidManifest();String oldPath = iremotePath + "\\app\\platformres\\" + folderName + "\\res";String newPath = iremotePath + "\\app\\src\\main\\res";System.out.println("厂家文件夹替换");copyFolder(oldPath,newPath);//修改build.gradle包名System.out.println("处理build.gradle包名");changeBuild();}/*** 读取版本信息*/public static void readPlatformXml(){if("1".equals(platform)){folderName = "baidu";}else if("2".equals(platform)){folderName = "google";}boolean isChange = false;String platformXmlPath = iremotePath + "\\app\\platformres\\" + folderName + "\\platform.xml";//厂商文件SAXBuilder builder = new SAXBuilder();Document document = null;try{InputStreamReader isr = new InputStreamReader(new FileInputStream(platformXmlPath), "UTF-8");InputSource is = new InputSource(isr);document = builder.build(is);}catch (Exception e) {e.printStackTrace();}Scanner scanner = new Scanner(System.in);Element data = document.getRootElement();//根节点-->manifestAttribute platforPackageAttr = data.getAttribute("package");Attribute versionAttr = data.getAttribute("version");if(platforPackageAttr == null){System.out.println("厂商" + folderName + "包名为空,请输入包名");platforPackage = scanner.next();data.setAttribute("package",platforPackage);isChange = true;}else{platforPackage = platforPackageAttr.getValue();}if(versionAttr == null){System.out.println("厂商" + folderName + "版本号为空,请输入版本号,格式:(1.0.00)");version = scanner.next();data.setAttribute("version",version);isChange = true;}else{version = versionAttr.getValue();System.out.println();System.out.println("当前app版本的版本号:" + version + ",是否需要修改,y为修改,任意键不修改");String str = scanner.next();if("y".equalsIgnoreCase(str)){while (true) {System.out.println("请输入新的版本号,格式:(1.0.00)");String versionStr = scanner.next();if(versionStr.matches("[0-9].[0].[0-9]{2}")){version = versionStr;data.setAttribute("version",version);isChange = true;break;}else if("n".equalsIgnoreCase(versionStr)){break;}System.out.println("格式有误,请重新输入,输入n退出");}isChange = true;}}if(isChange){try {System.out.println("readPlatformXml:" + platformXmlPath);doc2XML(document,platformXmlPath);} catch (Exception e) {e.printStackTrace();}}}public static void changeAndroidManifest(){String AndroidManifestPath = iremotePath + "\\app\\src\\main\\AndroidManifest.xml";//AndroidManifest文件地址SAXBuilder builder = new SAXBuilder();Document document = null;try{InputStreamReader isr = new InputStreamReader(new FileInputStream(AndroidManifestPath), "UTF-8");InputSource is = new InputSource(isr);document = builder.build(is);}catch (Exception e) {e.printStackTrace();}Element manifestElem = document.getRootElement();//根节点-->manifestmanifestElem.setAttribute("android:versionName",version);//APP版本manifestElem.setAttribute("android:versionCode",version.replace(".", ""));//APP版本Element permissionElem = manifestElem.getChild("permission");permissionElem.setAttribute("android:name",platforPackage + ".permission.JPUSH_MESSAGE");List<Element> usesPermissions = manifestElem.getChildren("uses-permission");//子节点集合for(Element elem : usesPermissions){String nameEle = elem.getAttribute("android:name").getValue();if(nameEle.indexOf(".permission.JPUSH_MESSAGE") > 0){elem.setAttribute("android:name",platforPackage + ".permission.JPUSH_MESSAGE");}}try {doc2XML(document,AndroidManifestPath);} catch (Exception e) {e.printStackTrace();}}/**   * DOCUMENT输出XML   *    * @param doc JDOM* @param filePath 输出的地址* @throws Exception   */    public static void doc2XML(Document doc, String filePath) throws Exception{Format format = Format.getCompactFormat();      format.setEncoding("UTF-8"); //字符编码UTF-8     format.setIndent("     ");//setIndent是设置分隔附的意思,一般都是用空格,就是当你新节点后,自动换行并缩进,有层次感,如果这样写setIndent(""),就只有换行功能,而不会缩进了,如果写成setIndent(null),这样就即不换行也不缩进,全部以一行显示了,默认的就是这样的效果,不好看。        format.setLineSeparator("\n");format.setEncodingOut(true);format.setAttributeLineSeparator(true);format.setAttributeSeparatorStr("\n");XMLOutputter outputter = new XMLOutputter(format);  OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8");  outputter.output(doc, writer);  writer.close();  }   private static void changeBuild(){  String buildName = iremotePath + "\\app\\build.gradle";//build.gradle文件地址try {// read file content from fileStringBuffer content= new StringBuffer("");InputStreamReader isr = new InputStreamReader(new FileInputStream(buildName), "UTF-8");BufferedReader br = new BufferedReader(isr);String str = null;while((str = br.readLine()) != null) {if (str.trim().startsWith("applicationId")) {  content.append("        applicationId \"" + platforPackage + "\"");  }else{content.append(str);  }content.append("\r\n");  }br.close();isr.close();Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(buildName), "UTF-8"));  writer.write(content.toString());  writer.close();}catch(FileNotFoundException e) {e.printStackTrace();}catch(IOException e) {e.printStackTrace();}}/**   *  复制整个文件夹内容   *  @param  oldPath  String  原文件路径  如:c:/fqf   *  @param  newPath  String  复制后路径  如:f:/fqf/ff   *  @return  boolean   */    public static void copyFolder(String  oldPath,  String  newPath)  {try  {    (new  File(newPath)).mkdirs();  //如果文件夹不存在  则建立新文件夹    File  a=new  File(oldPath);    String[]  file=a.list();    File  temp=null;    for  (int  i  =  0;  i  <  file.length;  i++)  {    if(oldPath.endsWith(File.separator)){    temp=new  File(oldPath+file[i]);    }    else{    temp=new  File(oldPath+File.separator+file[i]);    }    if(temp.isFile()){    FileInputStream  input  =  new  FileInputStream(temp);    FileOutputStream  output  =  new  FileOutputStream(newPath  +  "/"  +   (temp.getName()).toString());    byte[]  b  =  new  byte[1024  *  5];    int  len;    while  (  (len  =  input.read(b))  !=  -1)  {    output.write(b,  0,  len);    }    output.flush();    output.close();    input.close();    }    if(temp.isDirectory()){//如果是子文件夹    copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);    }    }    }    catch  (Exception  e)  {    System.out.println("复制整个文件夹内容操作出错");    e.printStackTrace();    }    }
}

这里面对AndroidManifest.xml的处理我用的是jdom.jar的包。但该jar包写入”android:xxx“结构的节点内容无法修改只能新增。因此,我对jdom的源码进行修改。
jdom.jar源码及Demo地址在文章末尾。

特比说明下,gradle的环境要与项目环境一致,否则会打包apk失败。
jdom源码
http://download.csdn.net/download/feiniyan4944/10178610
Demo源码
↓↓↓↓
http://download.csdn.net/download/feiniyan4944/10178500

APP多平台快速切换相关推荐

  1. 如何快速制作App应用软件?国内有哪些比较好用的App制作平台?

    如今,各类App让大家像淘金似往自个儿的爱机里装,无论是Apple Store还是安卓市场,应用商店总是手机控们的发烧地.但是这类门户却满足不了满脑子想法的动手一族,可惜他们只是梦想家,却不是程序猿, ...

  2. Unity中使用软连接快速切换平台

    Unity中使用软连接快速切换平台 Unity会把所有的资源在不同平台下进行不同的设置, 且每次切换平台都需要重新计算, 在大型项目中, 由于资源很多, 切换的成本比较高, 可能动不动的就是几十分钟, ...

  3. 快速生成APP的平台

    介绍了国内快速生成APP的平台与自己平台的对比,很有参考价值. 同类网站 安米网 http://www.appbyme.org/ 追信 http://app.zhui.cn/ 简网app工厂 http ...

  4. 安居客 Android App 走向平台化 | CSDN 博文精选

    作者 | 张磊 责编 | 屠敏 出品 | CSDN博客 安居客 Android App 距离上次的模块化/组件化重构已经两年多了,重构之后很好的支撑了两年多以来的业务发展.但这个世界总是在向前走的,没 ...

  5. # 飞书APP集成平台-数字化落地

    飞书APP集成平台-数字化落地 1. 多维表格助力项目管理 2. 看版视图-实现数据分类整理与可视化 3 三一重工"灯塔工厂"的数字化三个阶段 4. 伯镭科技的绿色智慧矿山无人驾驶 ...

  6. 安居客 Android App 走向平台化

    首发于微信公众号:BaronTalk 安居客 Android App 距离上次的模块化/组件化重构已经两年多了,重构之后很好的支撑了两年多以来的业务发展.但这个世界总是在向前走的,没有任何一种架构能够 ...

  7. 安居客 Android APP 走向平台化 | 开发者说·DTalk

    本文原作者: 张磊BARON,原文发布于微信公众号: BaronTalk  https://mp.weixin.qq.com/s/71VfmQ5ZyihgTwosMPbSmw 安居客 Android ...

  8. 开发安卓app游戏_游戏陪玩系统APP开发平台

    点击上方蓝字关注我们 游戏陪玩系统开发,找[金生:157-6875-2419微电],游戏陪玩系统定制开发平台,游戏陪玩系统开发模式,游戏陪玩系统APP开发平台 游戏陪玩软件开发 游戏陪玩系统源码搭建平 ...

  9. 源码推荐:仿写映客直播 ,快速切换主题 ,星星评分控件,表格样式,可以横向移动的表格, 仿微信键盘-

    仿写映客直播(上传者:五仁月饼) 工作之余写的,基于IJKPlayer播放,对内存做了处理.目前已完成直播列表和直播间的搭建,后续还会慢慢完善. 项目地址 publishImageAndVideoAn ...

最新文章

  1. 安装caffe(CPU版本)的一些参考和问题的解决
  2. 如果计算机用户有密码 待机,电脑待机密码怎么设置
  3. [蓝桥杯2019初赛]完全二叉树的权值-完全二叉树的性质
  4. 使用Python爬虫爬取网络美女图片
  5. ×××数据库导数据ora-01400错误小计
  6. 调整手机titlebar与app的titlebar相衔接
  7. Java基础之如何修改字符串?
  8. html%3c转译,[转]URL编码
  9. Pascal voc 数据集下载网址
  10. jQuery图片LightBox插件 点击图片放大 支持移动手机
  11. ADS 修改版图默认单位
  12. 周礼键君:中国福建省建瓯市之《闽郡八音字典》
  13. 一些思考:腾讯股价为何持续都低
  14. Python turtle画图之心形图案
  15. 判断浏览器必须是IE10以上,低于IE10做出提示
  16. 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)
  17. 摄像头在线测试_Leez学院| 面部检测 精准可靠 Leez P515 OpenCV工程测试
  18. shell 文件处理 并集 交集 差集
  19. ROS:服务数据(srv)的定义与使用
  20. SQL每日一题(20201218)来查找与之前(昨天的)日期相比温度更高的所有日期

热门文章

  1. 解决webpack打包css时CssSyntaxError的问题
  2. 多多客id是什么意思_【多多情报学堂】拼多多id是什么?拼多多店铺id在哪里看?...
  3. 微波技术大作业课设-分立电容电感+微带单枝短截线+微带双枝短截线
  4. 海南大学信号与系统838报考高频问题整理(五)
  5. 台式电脑脑计算机没法启动怎么办,台式机主机电源灯不亮,开不了机怎么办? 台式电脑无法开机什么原因...
  6. (转载)解决FileOutputStream中文乱码问题
  7. xdm linux,XDM (简体中文)
  8. GBase XDM 数据库ldapdelete命令讲解和示例分析
  9. Java中为按钮添加监听器(事件处理)四种形式总结
  10. java word合并单元格_java使用freemarker模板导出word(带有合并单元格)文档