Package com.yifanlu.PSXperiaTool

Source Code of com.yifanlu.PSXperiaTool.ApkBuilder

/*
* PSXperia Converter Tool - Logging
* Copyright (C) 2011 Yifan Lu (http://yifan.lu/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.yifanlu.PSXperiaTool;

import com.android.sdklib.internal.build.SignedJarBuilder;

import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;

public class ApkBuilder {
    private static final String ALIAS = "signPSXperia";
    private static final char[] KEYSTORE_PASSWORD = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
    private static final char[] ALIAS_PASSWORD = {'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
    public static final String VERSION = "0.3 Beta 2";

    private File mInputDir;
    private File mOutputApk;

    public ApkBuilder(File inputDir, File outputApk){
        this.mInputDir = inputDir;
        this.mOutputApk = outputApk;
    }

    public void buildApk() throws IOException, InterruptedException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException {
        String os = System.getProperty("os.name");
        Logger.verbose("Your OS: %s", os);
        File aaptTool;
        if(os.equals("Mac OS X"))
            aaptTool = new File("./aapt-osx");
        else if(os.startsWith("Windows"))
            aaptTool = new File("./aapt-windows.exe");
        else if(os.equals("Linux"))
            aaptTool = new File("./aapt-linux");
        else {
            Logger.warning("Does not understand OS name '%s', assuming to be Linux", os);
            aaptTool = new File("./aapt-linux");
        }
        InputStream in = PSXperiaTool.class.getResourceAsStream("/resources/" + aaptTool.getName());
        Logger.verbose("Extracting %s", aaptTool.getPath());
        writeStreamToFile(in, aaptTool);
        in.close();
        aaptTool.setExecutable(true);

        File androidFrameworkJar = new File("./android-framework.jar");
        Logger.verbose("Extracting %s", androidFrameworkJar.getPath());
        in = PSXperiaTool.class.getResourceAsStream("/resources/android-framework.jar");
        writeStreamToFile(in, androidFrameworkJar);
        in.close();

        File tempApk = new File(mOutputApk.getPath() + ".unsigned");

        String[] cmd = new String[12];
        cmd[0] = (aaptTool.getPath());
        cmd[1] = ("package");
        cmd[2] = ("-f");
        cmd[3] = ("-F");
        cmd[4] = (tempApk.getPath());
        cmd[5] = ("-S");
        cmd[6] = ((new File(mInputDir, "/res")).getPath());
        cmd[7] = ("-M");
        cmd[8] = ((new File(mInputDir, "/assets/AndroidManifest.xml")).getPath());
        cmd[9] = ("-I");
        cmd[10] = (androidFrameworkJar.getPath());
        cmd[11] = (mInputDir.getPath());
        Logger.debug("Running command: " + Arrays.toString(cmd).replaceAll("\\,", ""));
        runCmdWithOutput(cmd);

        Logger.info("Signing apk %s to %s", tempApk.getPath(), mOutputApk.getPath());
        signApk(tempApk);

        Logger.verbose("Cleaning up signing stuff.");
        tempApk.delete();
        androidFrameworkJar.delete();
        aaptTool.delete();
    }

    private void writeStreamToFile(InputStream in, File outFile) throws IOException {
        Logger.verbose("Writing to: %s", outFile.getPath());
        FileOutputStream out = new FileOutputStream(outFile);
        byte[] buffer = new byte[1024];
        int n;
        while((n = in.read(buffer)) != -1){
            out.write(buffer, 0, n);
        }
        out.close();
    }

    public static void runCmdWithOutput(String[] cmd) throws IOException, InterruptedException {
        Process ps = Runtime.getRuntime().exec(cmd);
        BufferedReader in = new BufferedReader(new InputStreamReader(ps.getErrorStream()));
        String line;
        while ((line = in.readLine()) != null) {
            Logger.debug(line);
        }
        in.close();
        if (ps.waitFor() != 0) {
            throw new IOException("Executable did not return without error.");
        }
    }

    private void signApk(File unsignedApk) throws IOException, GeneralSecurityException, SignedJarBuilder.IZipEntryFilter.ZipAbortException {
        FileInputStream in = new FileInputStream(unsignedApk);
        FileOutputStream out = new FileOutputStream(mOutputApk);
        KeyStore ks = getKeyStore();
        PrivateKey key = (PrivateKey)ks.getKey(ALIAS, ALIAS_PASSWORD);
        X509Certificate cert = (X509Certificate)ks.getCertificate(ALIAS);
        SignedJarBuilder builder = new SignedJarBuilder(out, key, cert);
        builder.writeZip(in, null);
        builder.close();
        out.close();
        in.close();
    }

    private KeyStore getKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        InputStream is = PSXperiaTool.class.getResourceAsStream("/resources/signApk.keystore");
        ks.load(is, KEYSTORE_PASSWORD);
        return ks;
    }
}
TOP

Related Classes of com.yifanlu.PSXperiaTool.ApkBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.