diff options
Diffstat (limited to 'anttasks/src/com/android/ant/ApkBuilderTask.java')
| -rw-r--r-- | anttasks/src/com/android/ant/ApkBuilderTask.java | 293 | 
1 files changed, 293 insertions, 0 deletions
| diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java new file mode 100644 index 0000000..22729ec --- /dev/null +++ b/anttasks/src/com/android/ant/ApkBuilderTask.java @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ant; + +import com.android.apkbuilder.ApkBuilder; +import com.android.apkbuilder.ApkBuilder.ApkFile; +import com.android.sdklib.project.ApkConfigurationHelper; +import com.android.sdklib.project.ProjectProperties; +import com.android.sdklib.project.ProjectProperties.PropertyType; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +public class ApkBuilderTask extends Task { +     +    /** +     * Class to represent nested elements. Since they all have only one attribute ('path'), the +     * same class can be used for all the nested elements (zip, file, sourcefolder, jarfolder, +     * nativefolder). +     */ +    public final static class Value extends ProjectComponent { +        String mPath; +         +        /** +         * Sets the value of the "path" attribute. +         * @param path the value. +         */ +        public void setPath(Path path) { +            mPath = path.toString(); +        } +    } + +    private String mOutFolder; +    private String mBaseName; +    private boolean mVerbose = false; +    private boolean mSigned = true; +     +    private final ArrayList<Value> mZipList = new ArrayList<Value>(); +    private final ArrayList<Value> mFileList = new ArrayList<Value>(); +    private final ArrayList<Value> mSourceList = new ArrayList<Value>(); +    private final ArrayList<Value> mJarList = new ArrayList<Value>(); +    private final ArrayList<Value> mNativeList = new ArrayList<Value>(); + +    private final ArrayList<FileInputStream> mZipArchives = new ArrayList<FileInputStream>(); +    private final ArrayList<File> mArchiveFiles = new ArrayList<File>(); +    private final ArrayList<ApkFile> mJavaResources = new ArrayList<ApkFile>(); +    private final ArrayList<FileInputStream> mResourcesJars = new ArrayList<FileInputStream>(); +    private final ArrayList<ApkFile> mNativeLibraries = new ArrayList<ApkFile>(); + +    /** +     * Sets the value of the "outfolder" attribute. +     * @param outFolder the value. +     */ +    public void setOutfolder(Path outFolder) { +        mOutFolder = outFolder.toString(); +    } +     +    /** +     * Sets the value of the "basename" attribute. +     * @param baseName the value. +     */ +    public void setBasename(String baseName) { +        mBaseName = baseName; +    } +     +    /** +     * Sets the value of the "verbose" attribute. +     * @param verbose the value. +     */ +    public void setVerbose(boolean verbose) { +        mVerbose = verbose; +    } +     +    /** +     * Sets the value of the "signed" attribute. +     * @param signed the value. +     */ +    public void setSigned(boolean signed) { +        mSigned = signed; +    } +     +    /** +     * Returns an object representing a nested <var>zip</var> element. +     */ +    public Object createZip() { +        Value zip = new Value(); +        mZipList.add(zip); +        return zip; +    } +     +    /** +     * Returns an object representing a nested <var>file</var> element. +     */ +    public Object createFile() { +        Value file = new Value(); +        mFileList.add(file); +        return file; +    } + +    /** +     * Returns an object representing a nested <var>sourcefolder</var> element. +     */ +    public Object createSourcefolder() { +        Value file = new Value(); +        mSourceList.add(file); +        return file; +    } + +    /** +     * Returns an object representing a nested <var>jarfolder</var> element. +     */ +    public Object createJarfolder() { +        Value file = new Value(); +        mJarList.add(file); +        return file; +    } +     +    /** +     * Returns an object representing a nested <var>nativefolder</var> element. +     */ +    public Object createNativefolder() { +        Value file = new Value(); +        mNativeList.add(file); +        return file; +    } +     +    @Override +    public void execute() throws BuildException { +        Project taskProject = getProject(); +         +        ApkBuilder apkBuilder = new ApkBuilder(); +        apkBuilder.setVerbose(mVerbose); +        apkBuilder.setSignedPackage(mSigned); +         +        try { +            // setup the list of everything that needs to go in the archive. +             +            // go through the list of zip files to add. This will not include +            // the resource package, which is handled separaly for each apk to create. +            for (Value v : mZipList) { +                FileInputStream input = new FileInputStream(v.mPath); +                mZipArchives.add(input); +            } +             +            // now go through the list of file to directly add the to the list. +            for (Value v : mFileList) { +                mArchiveFiles.add(ApkBuilder.getInputFile(v.mPath)); +            } +             +            // now go through the list of file to directly add the to the list. +            for (Value v : mSourceList) { +                ApkBuilder.processSourceFolderForResource(v.mPath, mJavaResources); +            } +             +            // now go through the list of jar folders. +            for (Value v : mJarList) { +                ApkBuilder.processJarFolder(v.mPath, mResourcesJars); +            } +             +            // now the native lib folder. +            for (Value v : mNativeList) { +                String parameter = v.mPath; +                File f = new File(parameter); +                 +                // compute the offset to get the relative path +                int offset = parameter.length(); +                if (parameter.endsWith(File.separator) == false) { +                    offset++; +                } + +                ApkBuilder.processNativeFolder(offset, f, mNativeLibraries); +            } + +             +            // first do a full resource package +            createApk(apkBuilder, null /*configName*/, null /*resourceFilter*/); +     +            // now see if we need to create file with filtered resources. +            // Get the project base directory. +            File baseDir = taskProject.getBaseDir(); +            ProjectProperties properties = ProjectProperties.load(baseDir.getAbsolutePath(), +                    PropertyType.DEFAULT); +             +            Map<String, String> apkConfigs = ApkConfigurationHelper.getConfigs(properties); +            if (apkConfigs.size() > 0) { +                Set<Entry<String, String>> entrySet = apkConfigs.entrySet(); +                for (Entry<String, String> entry : entrySet) { +                    createApk(apkBuilder, entry.getKey(), entry.getValue()); +                } +            } +        } catch (FileNotFoundException e) { +            throw new BuildException(e); +        } catch (IllegalArgumentException e) { +            throw new BuildException(e); +        } +    } +     +    /** +     * Creates an application package. +     * @param apkBuilder  +     * @param configName the name of the filter config. Can be null in which case a full resource +     * package will be generated. +     * @param resourceFilter the resource configuration filter to pass to aapt (if configName is +     * non null) +     * @throws FileNotFoundException  +     */ +    private void createApk(ApkBuilder apkBuilder, String configName, String resourceFilter) +            throws FileNotFoundException { +        // All the files to be included in the archive have already been prep'ed up, except +        // the resource package. +        // figure out its name. +        String filename; +        if (configName != null && resourceFilter != null) { +            filename = mBaseName + "-" + configName + ".ap_"; +        } else { +            filename = mBaseName + ".ap_"; +        } +         +        // now we add it to the list of zip archive (it's just a zip file). +         +        // it's used as a zip archive input +        FileInputStream resoucePackageZipFile = new FileInputStream(new File(mOutFolder, filename)); +        mZipArchives.add(resoucePackageZipFile); +         +        // prepare the filename to generate. Same thing as the resource file. +        if (configName != null && resourceFilter != null) { +            filename = mBaseName + "-" + configName; +        } else { +            filename = mBaseName; +        } +         +        if (mSigned) { +            filename = filename + "-debug.apk"; +        } else { +            filename = filename + "-unsigned.apk"; +        } + +        if (configName == null || resourceFilter == null) { +            if (mSigned) { +                System.out.println(String.format( +                        "Creating %s and signing it with a debug key...", filename)); +            } else { +                System.out.println(String.format( +                        "Creating %s for release...", filename)); +            } +        } else { +            if (mSigned) { +                System.out.println(String.format( +                        "Creating %1$s (with %2$s) and signing it with a debug key...", +                        filename, resourceFilter)); +            } else { +                System.out.println(String.format( +                        "Creating %1$s (with %2$s) for release...", +                        filename, resourceFilter)); +            } +        } +         +        File f = new File(mOutFolder, filename); +         +        // and generate the apk +        apkBuilder.createPackage(f.getAbsoluteFile(), mZipArchives, +                mArchiveFiles, mJavaResources, mResourcesJars, mNativeLibraries); +         +        // we are done. We need to remove the resource package from the list of zip archives +        // in case we have another apk to generate. +        mZipArchives.remove(resoucePackageZipFile); +    } +} | 
