以下是對一個已經打包的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.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 stub String 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 block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.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(); } }}
getSubStr.bat檔案 參考《getSubStr》
deleteDir.bat檔案 參考《deleteDir》
apktool.bat檔案 請參考《Android反編譯工具簡介》 robin.keystore檔案的製作 請參考《Android應用程式簽名簡介 》 android應用程式的AndroidManifest.xml檔案
結束!