Android快速批量打渠道包(AndroidManifestModifier)

本人博客原文: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.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文件
robin.keystore文件的制作
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" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
                <meta-data
            android:name="youmi:channel"
            android:value="88888" />
        <activity
            android: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>
        <activity
            android:name=".SignatureDetailActivity"
            android:label="@string/app_name" >
        </activity>
    </application>
</manifest>

结束!

Android快速批量打渠道包(AndroidManifestModifier),布布扣,bubuko.com

Android快速批量打渠道包(AndroidManifestModifier)

上一篇:使用PolarDB和ECS搭建门户网站


下一篇:磁盘管理命令