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

本人博客原文:http://hubingforever.blog.163.com/blog/static/1710405792013102954345842/

以下是对一个已经打包的Android应用程序的apk文件根据渠道号再进行批量打包的程序示例。
config.bat文件
set outDir=out
set rawDatadir=temp
set apk=S ignatureChecker.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文件

<? 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))