本人博客原文:http://hubingforever.blog.163.com/blog/static/1710405792013102954345842/
以下是对一个已经打包的Android应用程序的apk文件根据渠道号再进行批量打包的程序示例。
config.bat文件
set outDir=out
set rawDatadir=temp
set apk=SignatureChecker.apk
set channelName=A;B
set channelNo=1;2;3;4
set projectName=r
set versionCode=100
set stamp=%Date:~0,4%%Date:~5,2%%Date:~8,2%%Time:~0,2%%Time:~3,2%%Time:~6,2%
echo %stamp%_
build.bat文件
@echo off
call config.bat
Setlocal enabledelayedexpansion
set path=%path%;%cd%\lib
if exist %rawDatadir% (
call deleteDir %rawDatadir%
)
if not exist %outDir% (
md %outDir%
)
call apktool d -s %apk% %rawDatadir%
Setlocal enabledelayedexpansion
set /a cnt=0
for %%i in (%channelName%) do (
set name=%%i
set apkName=%projectName%_%versionCode%_!name!.apk
call getSubStr "%channelNo%" !cnt!
set no=!getSubStr~result!
set /a cnt+=1
java AndroidManifestModifier %rawDatadir%\AndroidManifest.xml %rawDatadir%\AndroidManifest.xml lenovo:channel !no!
call apktool b %rawDatadir% !apkName!
jarsigner -keystore robin.keystore -storepass GL2009 -keypass gl2009 !apkName! robin
move !apkName! %outDir%
)
endlocal
关于apktool请参考《Android反编译工具简介》,另外jarsigner就是JDK下载的一个工具。
AndroidManifestModifier主要用于在对Android应用程序进行打包发布是修改渠道号。
AndroidManifestModifier主要用于在对Android应用程序进行打包发布是修改渠道号。
AndroidManifestModifier.java文件
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.Writer;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import javax.xml.transform.OutputKeys;import javax.xml.transform.Result;import javax.xml.transform.Source;import javax.xml.transform.Transformer;import javax.xml.transform.TransformerConfigurationException;import javax.xml.transform.TransformerException;import javax.xml.transform.TransformerFactory;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.stream.StreamResult;import org.w3c.dom.Document;import org.w3c.dom.NamedNodeMap;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;public class AndroidManifestModifier {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubString srcFilePath="AndroidManifest.xml";String outFilePath="AndroidManifest.xml";String metaDataName="youmi:channel";String metaDataNewValue="newValue"+System.currentTimeMillis()%1000;if(args!=null&&args.length>=4){srcFilePath=args[0];outFilePath=args[1];metaDataName=args[2];metaDataNewValue=args[3];}change(srcFilePath,outFilePath,metaDataName,metaDataNewValue);}public static void change(String srcfilePath,String outFilePath,String metaDataName,String metaDataNewValue) {File f = new File(srcfilePath);DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = null;final String android_value="android:value";try {builder = factory.newDocumentBuilder();Document doc = builder.parse(f);NodeList nl = doc.getElementsByTagName("meta-data");int len = nl.getLength();org.w3c.dom.Node channelNode = null;for (int i = 0; i < len; i++) {org.w3c.dom.Node n = nl.item(i);System.out.println(n.getNodeName());NamedNodeMap nm = n.getAttributes();boolean c=false;for (int j = 0; j < nm.getLength(); j++) {org.w3c.dom.Node n2 = nm.item(j);System.out.println(n2.getNodeName() + "|" + n2.getNodeValue());if (metaDataName.equals(n2.getNodeValue())){c=true;break;}}if(c){for (int j = 0; j < nm.getLength(); j++) {org.w3c.dom.Node n2 = nm.item(j);if (android_value.equals(n2.getNodeName())) {channelNode=n2;break;}}}}if (channelNode != null) {channelNode.setNodeValue(metaDataNewValue);writeXMLFile(doc, outFilePath);}} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private static void writeXMLFile(Document doc, String outfile) {try {FileOutputStream fos = new FileOutputStream(outfile);OutputStreamWriter outwriter = new OutputStreamWriter(fos);writeXmlFile(doc, outwriter, "utf-8");outwriter.close();fos.close();} catch (Exception e) {e.printStackTrace();}}// 写入xml文件public static void writeXmlFile(Document doc, Writer w, String encoding) {try {Source source = new DOMSource(doc);Result result = new StreamResult(w);Transformer xformer = TransformerFactory.newInstance().newTransformer();xformer.setOutputProperty(OutputKeys.ENCODING, encoding);xformer.transform(source, result);} catch (TransformerConfigurationException e) {e.printStackTrace();} catch (TransformerException e) {e.printStackTrace();}}}
apktool.bat文件
请参考《Android反编译工具简介》
robin.keystore文件的制作
请参考《Android应用程序签名简介
》
android应用程序的AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.lenovo.robin"android:versionCode="1"android:versionName="1.0" ><uses-sdk android:minSdkVersion="8" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name" ><meta-dataandroid:name="youmi:channel"android:value="88888" /><activityandroid:name=".SignatureCheckerActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".SignatureDetailActivity"android:label="@string/app_name" ></activity></application></manifest>
结束!