diff options
author | Xavier Ducrohet <xav@android.com> | 2010-06-17 11:04:26 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-06-22 14:05:29 -0700 |
commit | 7c19dcf5aead68f4f6675db0bac6b495396e2967 (patch) | |
tree | 20dad20d7cd4f61c8e39cfc66d7dd311d6e70dc8 /anttasks | |
parent | 13b97d8b6a4137d9be28e60196eb6d44dee742fa (diff) | |
download | sdk-7c19dcf5aead68f4f6675db0bac6b495396e2967.zip sdk-7c19dcf5aead68f4f6675db0bac6b495396e2967.tar.gz sdk-7c19dcf5aead68f4f6675db0bac6b495396e2967.tar.bz2 |
New ApkBuilder class.
this is meant to replace the one previously in apkbuilder.jar and the
one in ADT, while being part of the public sdklib API so that other
tools can use it if needed (to deprecate the command line version)
Another changelist will rename the ApkBuilder classes inside
ADT to make things less confusing.
Change-Id: I13f2a09d8d507a85be33af3fe659d175819cb641
Diffstat (limited to 'anttasks')
-rw-r--r-- | anttasks/src/com/android/ant/ApkBuilderTask.java | 197 |
1 files changed, 95 insertions, 102 deletions
diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java index bec0417..bc5f53c 100644 --- a/anttasks/src/com/android/ant/ApkBuilderTask.java +++ b/anttasks/src/com/android/ant/ApkBuilderTask.java @@ -16,9 +16,10 @@ package com.android.ant; -import com.android.sdklib.internal.build.ApkBuilderHelper; -import com.android.sdklib.internal.build.ApkBuilderHelper.ApkCreationException; -import com.android.sdklib.internal.build.ApkBuilderHelper.ApkFile; +import com.android.sdklib.build.ApkBuilder; +import com.android.sdklib.build.ApkBuilder.ApkCreationException; +import com.android.sdklib.build.ApkBuilder.DuplicateFileException; +import com.android.sdklib.build.ApkBuilder.SealedApkException; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -26,12 +27,15 @@ 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.io.FilenameFilter; import java.util.ArrayList; +import java.util.regex.Pattern; public class ApkBuilderTask extends Task { + private final static Pattern PATTERN_JAR_EXT = Pattern.compile("^.+\\.jar$", + Pattern.CASE_INSENSITIVE); + private String mOutFolder; @Deprecated private String mBaseName; private String mApkFilepath; @@ -42,20 +46,15 @@ public class ApkBuilderTask extends Task { private boolean mHasCode = true; private String mAbiFilter = null; + private Path mDexPath; + private final ArrayList<Path> mZipList = new ArrayList<Path>(); - private final ArrayList<Path> mDexList = new ArrayList<Path>(); private final ArrayList<Path> mFileList = new ArrayList<Path>(); private final ArrayList<Path> mSourceList = new ArrayList<Path>(); private final ArrayList<Path> mJarfolderList = new ArrayList<Path>(); private final ArrayList<Path> mJarfileList = new ArrayList<Path>(); private final ArrayList<Path> mNativeList = new ArrayList<Path>(); - 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. @@ -70,7 +69,7 @@ public class ApkBuilderTask extends Task { * @deprecated */ public void setBasename(String baseName) { - System.out.println("WARNNG: Using deprecated 'basename' attribute in ApkBuilderTask." + + System.out.println("WARNING: Using deprecated 'basename' attribute in ApkBuilderTask." + "Use 'apkfilepath' (path) instead."); mBaseName = baseName; } @@ -154,15 +153,19 @@ public class ApkBuilderTask extends Task { * is <code>false</code> in which case it's ignored. */ public Object createDex() { - Path path = new Path(getProject()); - mDexList.add(path); - return path; + if (mDexPath == null) { + return mDexPath = new Path(getProject()); + } else { + throw new BuildException("Only one <dex> inner element can be provided"); + } } /** * Returns an object representing a nested <var>file</var> element. */ public Object createFile() { + System.out.println("WARNING: Using deprecated <file> inner element in ApkBuilderTask." + + "Use <dex path=...> instead."); Path path = new Path(getProject()); mFileList.add(path); return path; @@ -208,36 +211,70 @@ public class ApkBuilderTask extends Task { public void execute() throws BuildException { Project antProject = getProject(); - ApkBuilderHelper apkBuilder = new ApkBuilderHelper(); - apkBuilder.setVerbose(mVerbose); - apkBuilder.setSignedPackage(mSigned); - apkBuilder.setDebugMode(mDebug); + // get the rules revision to figure out how to build the output file. + String rulesRevStr = antProject.getProperty(TaskHelper.PROP_RULES_REV); + int rulesRev = 1; + try { + rulesRev = Integer.parseInt(rulesRevStr); + } catch (NumberFormatException e) { + // this shouldn't happen since setup task is the one setting up every time. + } + + File outputFile; + if (mApkFilepath != null) { + outputFile = new File(mApkFilepath); + } else if (rulesRev == 2) { + if (mSigned) { + outputFile = new File(mOutFolder, mBaseName + "-debug-unaligned.apk"); + } else { + outputFile = new File(mOutFolder, mBaseName + "-unsigned.apk"); + } + } else { + throw new BuildException("missing attribute 'apkFilepath'"); + } + + // check dexPath is only one file. + File dexFile = null; + if (mHasCode) { + String[] dexFiles = mDexPath.list(); + if (dexFiles.length != 1) { + throw new BuildException(String.format( + "Expected one dex file but path value resolve to %d files.", + dexFiles.length)); + } + dexFile = new File(dexFiles[0]); + } try { - // setup the list of everything that needs to go in the archive. + if (mSigned) { + System.out.println(String.format( + "Creating %s and signing it with a debug key...", outputFile.getName())); + } else { + System.out.println(String.format( + "Creating %s for release...", outputFile.getName())); + } - // 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. + ApkBuilder apkBuilder = new ApkBuilder( + outputFile, + new File(mOutFolder, mResourceFile), + dexFile, + mSigned ? ApkBuilder.getDebugKeystore() : null, + mVerbose ? System.out : null); + apkBuilder.setDebugMode(mDebug); + + + // add the content of the zip files. for (Path pathList : mZipList) { for (String path : pathList.list()) { - FileInputStream input = new FileInputStream(path); - mZipArchives.add(input); + apkBuilder.addZipFile(new File(path)); } } - // now go through the list of file to directly add the to the list. + // add the files that go to the root of the archive (this is deprecated) for (Path pathList : mFileList) { for (String path : pathList.list()) { - mArchiveFiles.add(ApkBuilderHelper.getInputFile(path)); - } - } - - // only attempt to add Dex files if hasCode is true. - if (mHasCode) { - for (Path pathList : mDexList) { - for (String path : pathList.list()) { - mArchiveFiles.add(ApkBuilderHelper.getInputFile(path)); - } + File f = new File(path); + apkBuilder.addFile(f, f.getName()); } } @@ -245,8 +282,7 @@ public class ApkBuilderTask extends Task { if (mHasCode) { for (Path pathList : mSourceList) { for (String path : pathList.list()) { - ApkBuilderHelper.processSourceFolderForResource(new File(path), - mJavaResources); + apkBuilder.addSourceFolder(new File(path)); } } } @@ -257,7 +293,15 @@ public class ApkBuilderTask extends Task { // it's ok if top level folders are missing File folder = new File(path); if (folder.isDirectory()) { - ApkBuilderHelper.processJar(folder, mResourcesJars); + String[] filenames = folder.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return PATTERN_JAR_EXT.matcher(name).matches(); + } + }); + + for (String filename : filenames) { + apkBuilder.addResourcesFromJar(new File(folder, filename)); + } } } } @@ -265,7 +309,7 @@ public class ApkBuilderTask extends Task { // now go through the list of jar files. for (Path pathList : mJarfileList) { for (String path : pathList.list()) { - ApkBuilderHelper.processJar(new File(path), mResourcesJars); + apkBuilder.addResourcesFromJar(new File(path)); } } @@ -275,77 +319,26 @@ public class ApkBuilderTask extends Task { // it's ok if top level folders are missing File folder = new File(path); if (folder.isDirectory()) { - ApkBuilderHelper.processNativeFolder(folder, mDebug, - mNativeLibraries, mVerbose, mAbiFilter); + apkBuilder.addNativeLibraries(folder, mAbiFilter); } } } - // get the rules revision - String rulesRevStr = antProject.getProperty(TaskHelper.PROP_RULES_REV); - int rulesRev = 1; - try { - rulesRev = Integer.parseInt(rulesRevStr); - } catch (NumberFormatException e) { - // this shouldn't happen since setup task is the one setting up every time. - } - - - File file; - if (mApkFilepath != null) { - file = new File(mApkFilepath); - } else if (rulesRev == 2) { - if (mSigned) { - file = new File(mOutFolder, mBaseName + "-debug-unaligned.apk"); - } else { - file = new File(mOutFolder, mBaseName + "-unsigned.apk"); - } - } else { - throw new BuildException("missing attribute 'apkFilepath'"); - } - // create the package. - createApk(apkBuilder, file); + // close the archive + apkBuilder.sealApk(); - } catch (FileNotFoundException e) { - throw new BuildException(e); - } catch (IllegalArgumentException e) { + } catch (DuplicateFileException e) { + System.err.println(String.format( + "Found duplicate file for APK: %1$s\nOrigin 1: %2$s\nOrigin 2: %3$s", + e.getArchivePath(), e.getFile1(), e.getFile2())); throw new BuildException(e); } catch (ApkCreationException e) { - e.printStackTrace(); + throw new BuildException(e); + } catch (SealedApkException e) { + throw new BuildException(e); + } catch (IllegalArgumentException e) { throw new BuildException(e); } } - - /** - * Creates an application package. - * @param apkBuilder - * @param outputfile the file to generate - * @throws FileNotFoundException - * @throws ApkCreationException - */ - private void createApk(ApkBuilderHelper apkBuilder, File outputfile) - throws FileNotFoundException, ApkCreationException { - - // add the resource pack file as a zip archive input. - FileInputStream resoucePackageZipFile = new FileInputStream( - new File(mOutFolder, mResourceFile)); - mZipArchives.add(resoucePackageZipFile); - - if (mSigned) { - System.out.println(String.format( - "Creating %s and signing it with a debug key...", outputfile.getName())); - } else { - System.out.println(String.format( - "Creating %s for release...", outputfile.getName())); - } - - // and generate the apk - apkBuilder.createPackage(outputfile.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); - } } |