diff options
Diffstat (limited to 'anttasks')
-rw-r--r-- | anttasks/src/com/android/ant/MultiApkExportTask.java | 385 |
1 files changed, 0 insertions, 385 deletions
diff --git a/anttasks/src/com/android/ant/MultiApkExportTask.java b/anttasks/src/com/android/ant/MultiApkExportTask.java deleted file mode 100644 index 6b23162..0000000 --- a/anttasks/src/com/android/ant/MultiApkExportTask.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (C) 2010 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.sdklib.internal.export.ApkData; -import com.android.sdklib.internal.export.MultiApkExportHelper; -import com.android.sdklib.internal.export.ProjectConfig; -import com.android.sdklib.internal.export.MultiApkExportHelper.ExportException; -import com.android.sdklib.internal.export.MultiApkExportHelper.Target; -import com.android.sdklib.internal.project.ProjectProperties; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.taskdefs.Input; -import org.apache.tools.ant.taskdefs.Property; -import org.apache.tools.ant.taskdefs.SubAnt; -import org.apache.tools.ant.types.FileSet; -import org.xml.sax.InputSource; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - -/** - * Multiple APK export task. - * This task is meant to replace {@link SetupTask} as the main setup/export task, importing - * the rules and generating the export for all projects. - */ -public class MultiApkExportTask extends Task { - - private static final String PROP_OUT_ABS_DIR = "out.absolute.dir"; - - private static final String PROP_KEY_STORE_PASSWORD = "key.store.password"; - private static final String PROP_KEY_ALIAS_PASSWORD = "key.alias.password"; - - - private Target mTarget; - private XPathFactory mXPathFactory; - - public void setTarget(String target) { - mTarget = Target.getTarget(target); - } - - @Override - public void execute() throws BuildException { - Project antProject = getProject(); - - if (mTarget == null) { - throw new BuildException("'target' attribute not set."); - } - - // get the SDK location - File sdk = TaskHelper.getSdkLocation(antProject); - - // display SDK Tools revision - int toolsRevison = TaskHelper.getToolsRevision(sdk); - if (toolsRevison != -1) { - System.out.println("Android SDK Tools Revision " + toolsRevison); - } - - String appPackage = getValidatedProperty(antProject, ProjectProperties.PROPERTY_PACKAGE); - System.out.println("Multi APK export for: " + appPackage); - String version = getValidatedProperty(antProject, ProjectProperties.PROPERTY_VERSIONCODE); - int versionCode; - try { - versionCode = Integer.parseInt(version); - } catch (NumberFormatException e) { - throw new BuildException("version value is not a valid integer.", e); - } - System.out.println("versionCode: " + version); - - // get the list of projects - String projectList = getValidatedProperty(antProject, "projects"); - - File rootFolder = antProject.getBaseDir(); - MultiApkExportHelper helper = new MultiApkExportHelper(rootFolder.getAbsolutePath(), - appPackage, versionCode, mTarget, System.out); - - try { - if (mTarget == Target.CLEAN) { - // for a clean, we don't need the list of ApkData, we only need the list of - // projects - List<ProjectConfig> projects = helper.getProjects(projectList); - for (ProjectConfig projectConfig : projects) { - executeCleanSubAnt(antProject, projectConfig); - } - } else { - // checks whether the projects can be signed. - String value = antProject.getProperty(ProjectProperties.PROPERTY_KEY_STORE); - String keyStore = value != null && value.length() > 0 ? value : null; - value = antProject.getProperty(ProjectProperties.PROPERTY_KEY_ALIAS); - String keyAlias = value != null && value.length() > 0 ? value : null; - boolean canSign = keyStore != null && keyAlias != null; - - List<ApkData> apks = helper.getApkData(projectList); - - // some temp var used by the project loop - HashSet<String> compiledProject = new HashSet<String>(); - mXPathFactory = XPathFactory.newInstance(); - - File exportProjectOutput = new File( - getValidatedProperty(antProject, PROP_OUT_ABS_DIR)); - - // if there's no error, and we can sign, prompt for the passwords. - String keyStorePassword = null; - String keyAliasPassword = null; - if (canSign) { - System.out.println("Found signing keystore and key alias. Need passwords."); - - Input input = new Input(); - input.setProject(antProject); - input.setAddproperty(PROP_KEY_STORE_PASSWORD); - input.setMessage(String.format("Please enter keystore password (store: %1$s):", - keyStore)); - input.execute(); - - input = new Input(); - input.setProject(antProject); - input.setAddproperty(PROP_KEY_ALIAS_PASSWORD); - input.setMessage(String.format("Please enter password for alias '%1$s':", - keyAlias)); - input.execute(); - - // and now read the property so that they can be set into the sub ant task. - keyStorePassword = getValidatedProperty(antProject, PROP_KEY_STORE_PASSWORD); - keyAliasPassword = getValidatedProperty(antProject, PROP_KEY_ALIAS_PASSWORD); - } - - for (ApkData apk : apks) { - - Map<String, String> variantMap = apk.getSoftVariantMap(); - - if (variantMap.size() > 0) { - // if there are soft variants, only export those. - for (Entry<String, String> entry : variantMap.entrySet()) { - executeReleaseSubAnt(antProject, appPackage, versionCode, apk, entry, - exportProjectOutput, canSign, keyStore, keyAlias, - keyStorePassword, keyAliasPassword, compiledProject); - } - } else { - // do the full export. - executeReleaseSubAnt(antProject, appPackage, versionCode, apk, null, - exportProjectOutput, canSign, keyStore, keyAlias, - keyStorePassword, keyAliasPassword, compiledProject); - - } - } - - helper.writeLogs(); - } - } catch (ExportException e) { - // we only want to have Ant display the message, not the stack trace, since - // we use Exceptions to report errors, so we build the BuildException only - // with the message and not the cause exception. - throw new BuildException(e.getMessage()); - } - } - - /** - * Creates and execute a clean sub ant task. - * @param antProject the current Ant project - * @param projectConfig the project to clean. - */ - private void executeCleanSubAnt(Project antProject, ProjectConfig projectConfig) { - - String relativePath = projectConfig.getRelativePath(); - - // this output is prepended by "[android-export] " (17 chars), so we put 61 stars - System.out.println("\n*************************************************************"); - System.out.println("Cleaning project: " + relativePath); - - SubAnt subAnt = new SubAnt(); - subAnt.setTarget(mTarget.getTarget()); - subAnt.setProject(antProject); - - File subProjectFolder = projectConfig.getProjectFolder(); - - FileSet fileSet = new FileSet(); - fileSet.setProject(antProject); - fileSet.setDir(subProjectFolder); - fileSet.setIncludes("build.xml"); - subAnt.addFileset(fileSet); - - // TODO: send the verbose flag from the main build.xml to the subAnt project. - //subAnt.setVerbose(true); - - // 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(); - } - - /** - * Creates and executes a release 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 executeReleaseSubAnt(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) { - - String relativePath = apk.getProjectConfig().getRelativePath(); - - // this output is prepended by "[android-export] " (17 chars), so we put 61 stars - System.out.println("\n*************************************************************"); - System.out.println("Exporting project: " + relativePath); - - SubAnt subAnt = new SubAnt(); - subAnt.setTarget(mTarget.getTarget()); - subAnt.setProject(antProject); - - File subProjectFolder = apk.getProjectConfig().getProjectFolder(); - - FileSet fileSet = new FileSet(); - fileSet.setProject(antProject); - fileSet.setDir(subProjectFolder); - fileSet.setIncludes("build.xml"); - subAnt.addFileset(fileSet); - - // TODO: send the verbose flag from the main build.xml to the subAnt project. - //subAnt.setVerbose(true); - - // 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(relativePath) == false) { - compiledProject.add(relativePath); - } 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, ProjectProperties.PROPERTY_KEY_STORE, keyStore); - addProp(subAnt, ProjectProperties.PROPERTY_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, ProjectProperties.PROPERTY_KEY_STORE, ""); - addProp(subAnt, ProjectProperties.PROPERTY_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 - * @param name the name of the property to return. - * @return the property value always (cannot be null). - * @throws BuildException if the property is missing or not valid. - */ - private String getValidatedProperty(Project antProject, String name) { - String value = antProject.getProperty(name); - if (value == null || value.length() == 0) { - throw new BuildException(String.format("Property '%1$s' is not set or empty.", name)); - } - - return value; - } - - /** - * Adds a property to a {@link SubAnt} task. - * @param task the task. - * @param name the name of the property. - * @param value the value of the property. - */ - private void addProp(SubAnt task, String name, String value) { - Property prop = new Property(); - prop.setName(name); - prop.setValue(value); - task.addProperty(prop); - } -} |