aboutsummaryrefslogtreecommitdiffstats
path: root/anttasks
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-06-01 17:00:00 -0700
committerXavier Ducrohet <xav@android.com>2010-06-01 19:43:02 -0700
commit8de0ba71344622c7bbe6699a6adb0804e0cd7094 (patch)
tree4365d6b28ab5be4898dd938dd3913074b82a118c /anttasks
parentfd6c6d2a823a98d885d24626c520a242d40fb9a2 (diff)
downloadsdk-8de0ba71344622c7bbe6699a6adb0804e0cd7094.zip
sdk-8de0ba71344622c7bbe6699a6adb0804e0cd7094.tar.gz
sdk-8de0ba71344622c7bbe6699a6adb0804e0cd7094.tar.bz2
Add support for soft properties in multi-apk export.
First property is split by density. Change-Id: If68bc520ba4014bbd4b144e71d54bc1161a56e2d
Diffstat (limited to 'anttasks')
-rw-r--r--anttasks/src/com/android/ant/MultiApkExportTask.java256
1 files changed, 157 insertions, 99 deletions
diff --git a/anttasks/src/com/android/ant/MultiApkExportTask.java b/anttasks/src/com/android/ant/MultiApkExportTask.java
index 8c9ee3e..fd33b92 100644
--- a/anttasks/src/com/android/ant/MultiApkExportTask.java
+++ b/anttasks/src/com/android/ant/MultiApkExportTask.java
@@ -36,6 +36,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
@@ -49,6 +52,7 @@ import javax.xml.xpath.XPathFactory;
public class MultiApkExportTask extends Task {
private Target mTarget;
+ private XPathFactory mXPathFactory;
public void setTarget(String target) {
mTarget = Target.getTarget(target);
@@ -105,9 +109,10 @@ public class MultiApkExportTask extends Task {
// some temp var used by the project loop
HashSet<String> compiledProject = new HashSet<String>();
- XPathFactory xPathFactory = XPathFactory.newInstance();
+ mXPathFactory = XPathFactory.newInstance();
- File exportProjectOutput = new File(getValidatedProperty(antProject, "out.absolute.dir"));
+ File exportProjectOutput = new File(getValidatedProperty(antProject,
+ "out.absolute.dir"));
// if there's no error, and we can sign, prompt for the passwords.
String keyStorePassword = null;
@@ -135,105 +140,21 @@ public class MultiApkExportTask extends Task {
}
for (ApkData apk : apks) {
- // this output is prepended by "[android-export] " (17 chars), so we put 61 stars
- System.out.println("\n*************************************************************");
- System.out.println("Exporting project: " + apk.getRelativePath());
-
- SubAnt subAnt = new SubAnt();
- subAnt.setTarget(mTarget.getTarget());
- subAnt.setProject(antProject);
-
- File subProjectFolder = new File(antProject.getBaseDir(), apk.getRelativePath());
-
- FileSet fileSet = new FileSet();
- fileSet.setProject(antProject);
- fileSet.setDir(subProjectFolder);
- fileSet.setIncludes("build.xml");
- subAnt.addFileset(fileSet);
-
- // subAnt.setVerbose(true);
-
- if (mTarget == Target.RELEASE) {
- // only do the compilation part if it's the first time we export
- // this project.
- // (projects can be export multiple time if some properties are set up to
- // generate more than one APK (for instance ABI split).
- if (compiledProject.contains(apk.getRelativePath()) == false) {
- compiledProject.add(apk.getRelativePath());
- } else {
- addProp(subAnt, "do.not.compile", "true");
- }
-
- // set the version code, and filtering
- int compositeVersionCode = apk.getCompositeVersionCode(versionCode);
- addProp(subAnt, "version.code", Integer.toString(compositeVersionCode));
- System.out.println("Composite versionCode: " + compositeVersionCode);
- String abi = apk.getAbi();
- if (abi != null) {
- addProp(subAnt, "filter.abi", abi);
- System.out.println("ABI Filter: " + abi);
- }
-
- // end of the output by this task. Everything that follows will be output
- // by the subant.
- System.out.println("Calling to project's Ant file...");
- System.out.println("----------\n");
-
- // set the output file names/paths. Keep all the temporary files in the project
- // folder, and only put the final file (which is different depending on whether
- // the file can be signed) locally.
-
- // read the base name from the build.xml file.
- String name = null;
- try {
- File buildFile = new File(subProjectFolder, "build.xml");
- XPath xPath = xPathFactory.newXPath();
- name = xPath.evaluate("/project/@name",
- new InputSource(new FileInputStream(buildFile)));
- } catch (XPathExpressionException e) {
- throw new BuildException("Failed to read build.xml", e);
- } catch (FileNotFoundException e) {
- throw new BuildException("build.xml is missing.", e);
- }
-
- // override the resource pack file.
- addProp(subAnt, "resource.package.file.name",
- name + "-" + apk.getBuildInfo() + ".ap_");
-
- if (canSign) {
- // set the properties for the password.
- addProp(subAnt, "key.store", keyStore);
- addProp(subAnt, "key.alias", keyAlias);
- addProp(subAnt, "key.store.password", keyStorePassword);
- addProp(subAnt, "key.alias.password", keyAliasPassword);
-
- // temporary file only get a filename change (still stored in the project
- // bin folder).
- addProp(subAnt, "out.unsigned.file.name",
- name + "-" + apk.getBuildInfo() + "-unsigned.apk");
- addProp(subAnt, "out.unaligned.file",
- name + "-" + apk.getBuildInfo() + "-unaligned.apk");
-
- // final file is stored locally.
- apk.setOutputName(name + "-" + compositeVersionCode + "-release.apk");
- addProp(subAnt, "out.release.file", new File(exportProjectOutput,
- apk.getOutputName()).getAbsolutePath());
-
- } else {
- // put some empty prop. This is to override possible ones defined in the
- // project. The reason is that if there's more than one project, we don't
- // want some to signed and some not to be (and we don't want each project
- // to prompt for password.)
- addProp(subAnt, "key.store", "");
- addProp(subAnt, "key.alias", "");
- // final file is the unsigned version. It gets stored locally.
- apk.setOutputName(name + "-" + compositeVersionCode + "-unsigned.apk");
- addProp(subAnt, "out.unsigned.file", new File(exportProjectOutput,
- apk.getOutputName()).getAbsolutePath());
- }
+
+ Map<String, String> variantMap = apk.getSoftVariantMap();
+
+ // first, do the full export.
+ makeSubAnt(antProject, appPackage, versionCode, apk, null,
+ exportProjectOutput, canSign, keyStore, keyAlias,
+ keyStorePassword, keyAliasPassword, compiledProject);
+
+ // then do the soft variants.
+ for (Entry<String, String> entry : variantMap.entrySet()) {
+ makeSubAnt(antProject, appPackage, versionCode, apk, entry,
+ exportProjectOutput, canSign, keyStore, keyAlias,
+ keyStorePassword, keyAliasPassword, compiledProject);
}
- subAnt.execute();
}
if (mTarget == Target.RELEASE) {
@@ -248,6 +169,143 @@ public class MultiApkExportTask extends Task {
}
/**
+ * Creates and executes a sub ant task.
+ * @param antProject the current Ant project
+ * @param appPackage the application package string.
+ * @param versionCode the current version of the application
+ * @param apk the {@link ApkData} being exported.
+ * @param softVariant the soft variant being exported, or null, if this is a full export.
+ * @param exportProjectOutput the folder in which the files must be exported.
+ * @param canSign whether the application package can be signed. This is dependent on the
+ * availability of some required values.
+ * @param keyStore the path to the keystore for signing
+ * @param keyAlias the alias of the key to be used for signing
+ * @param keyStorePassword the password of the keystore for signing
+ * @param keyAliasPassword the password of the key alias for signing
+ * @param compiledProject a list of projects that have already been compiled.
+ */
+ private void makeSubAnt(Project antProject, String appPackage, int versionCode,
+ ApkData apk, Entry<String, String> softVariant, File exportProjectOutput,
+ boolean canSign, String keyStore, String keyAlias,
+ String keyStorePassword, String keyAliasPassword, Set<String> compiledProject) {
+
+ // this output is prepended by "[android-export] " (17 chars), so we put 61 stars
+ System.out.println("\n*************************************************************");
+ System.out.println("Exporting project: " + apk.getRelativePath());
+
+ SubAnt subAnt = new SubAnt();
+ subAnt.setTarget(mTarget.getTarget());
+ subAnt.setProject(antProject);
+
+ File subProjectFolder = new File(antProject.getBaseDir(), apk.getRelativePath());
+
+ FileSet fileSet = new FileSet();
+ fileSet.setProject(antProject);
+ fileSet.setDir(subProjectFolder);
+ fileSet.setIncludes("build.xml");
+ subAnt.addFileset(fileSet);
+
+// subAnt.setVerbose(true);
+
+ if (mTarget == Target.RELEASE) {
+ // only do the compilation part if it's the first time we export
+ // this project.
+ // (projects can be export multiple time if some properties are set up to
+ // generate more than one APK (for instance ABI split).
+ if (compiledProject.contains(apk.getRelativePath()) == false) {
+ compiledProject.add(apk.getRelativePath());
+ } else {
+ addProp(subAnt, "do.not.compile", "true");
+ }
+
+ // set the version code, and filtering
+ int compositeVersionCode = apk.getCompositeVersionCode(versionCode);
+ addProp(subAnt, "version.code", Integer.toString(compositeVersionCode));
+ System.out.println("Composite versionCode: " + compositeVersionCode);
+ String abi = apk.getAbi();
+ if (abi != null) {
+ addProp(subAnt, "filter.abi", abi);
+ System.out.println("ABI Filter: " + abi);
+ }
+
+ // set the output file names/paths. Keep all the temporary files in the project
+ // folder, and only put the final file (which is different depending on whether
+ // the file can be signed) locally.
+
+ // read the base name from the build.xml file.
+ String name = null;
+ try {
+ File buildFile = new File(subProjectFolder, "build.xml");
+ XPath xPath = mXPathFactory.newXPath();
+ name = xPath.evaluate("/project/@name",
+ new InputSource(new FileInputStream(buildFile)));
+ } catch (XPathExpressionException e) {
+ throw new BuildException("Failed to read build.xml", e);
+ } catch (FileNotFoundException e) {
+ throw new BuildException("build.xml is missing.", e);
+ }
+
+ // override the resource pack file as well as the final name
+ String pkgName = name + "-" + apk.getBuildInfo();
+ String finalNameRoot = appPackage + "-" + compositeVersionCode;
+ if (softVariant != null) {
+ String tmp = "-" + softVariant.getKey();
+ pkgName += tmp;
+ finalNameRoot += tmp;
+
+ // set the resource filter.
+ addProp(subAnt, "aapt.resource.filter", softVariant.getValue());
+ System.out.println("res Filter: " + softVariant.getValue());
+ }
+
+ // set the resource pack file name.
+ addProp(subAnt, "resource.package.file.name", pkgName + ".ap_");
+
+
+ if (canSign) {
+ // set the properties for the password.
+ addProp(subAnt, "key.store", keyStore);
+ addProp(subAnt, "key.alias", keyAlias);
+ addProp(subAnt, "key.store.password", keyStorePassword);
+ addProp(subAnt, "key.alias.password", keyAliasPassword);
+
+ // temporary file only get a filename change (still stored in the project
+ // bin folder).
+ addProp(subAnt, "out.unsigned.file.name",
+ name + "-" + apk.getBuildInfo() + "-unsigned.apk");
+ addProp(subAnt, "out.unaligned.file",
+ name + "-" + apk.getBuildInfo() + "-unaligned.apk");
+
+ // final file is stored locally with a name based on the package
+ String outputName = finalNameRoot + "-release.apk";
+ apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName);
+ addProp(subAnt, "out.release.file",
+ new File(exportProjectOutput, outputName).getAbsolutePath());
+
+ } else {
+ // put some empty prop. This is to override possible ones defined in the
+ // project. The reason is that if there's more than one project, we don't
+ // want some to signed and some not to be (and we don't want each project
+ // to prompt for password.)
+ addProp(subAnt, "key.store", "");
+ addProp(subAnt, "key.alias", "");
+ // final file is the unsigned version. It gets stored locally.
+ String outputName = finalNameRoot + "-unsigned.apk";
+ apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName);
+ addProp(subAnt, "out.unsigned.file",
+ new File(exportProjectOutput, outputName).getAbsolutePath());
+ }
+ }
+
+ // end of the output by this task. Everything that follows will be output
+ // by the subant.
+ System.out.println("Calling to project's Ant file...");
+ System.out.println("----------\n");
+
+ subAnt.execute();
+ }
+
+ /**
* Gets, validates and returns a project property.
* The property must exist and be non empty.
* @param antProject the project