Make the Ant script sign and zipalign release builds.

It will also align debug builds.
BUG: 2052744
This commit is contained in:
Xavier Ducrohet
2009-08-13 16:49:40 -07:00
parent 0cef5c4666
commit 954e80e5ca
3 changed files with 101 additions and 25 deletions

View File

@@ -28,6 +28,7 @@ import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.Task; import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Path.PathElement;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@@ -39,6 +40,9 @@ import java.util.Map.Entry;
public class ApkBuilderTask extends Task { public class ApkBuilderTask extends Task {
// ref id to the <path> object containing all the boot classpaths.
private final static String REF_APK_PATH = "android.apks.path";
/** /**
* Class to represent nested elements. Since they all have only one attribute ('path'), the * 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, * same class can be used for all the nested elements (zip, file, sourcefolder, jarfolder,
@@ -152,7 +156,7 @@ public class ApkBuilderTask extends Task {
@Override @Override
public void execute() throws BuildException { public void execute() throws BuildException {
Project taskProject = getProject(); Project antProject = getProject();
ApkBuilderImpl apkBuilder = new ApkBuilderImpl(); ApkBuilderImpl apkBuilder = new ApkBuilderImpl();
apkBuilder.setVerbose(mVerbose); apkBuilder.setVerbose(mVerbose);
@@ -197,13 +201,16 @@ public class ApkBuilderTask extends Task {
ApkBuilderImpl.processNativeFolder(offset, f, mNativeLibraries); ApkBuilderImpl.processNativeFolder(offset, f, mNativeLibraries);
} }
// create the Path item that will contain all the generated APKs
// for reuse by other targets (signing/zipaligning)
Path path = new Path(antProject);
// first do a full resource package // first do a full resource package
createApk(apkBuilder, null /*configName*/, null /*resourceFilter*/); createApk(apkBuilder, null /*configName*/, null /*resourceFilter*/, path);
// now see if we need to create file with filtered resources. // now see if we need to create file with filtered resources.
// Get the project base directory. // Get the project base directory.
File baseDir = taskProject.getBaseDir(); File baseDir = antProject.getBaseDir();
ProjectProperties properties = ProjectProperties.load(baseDir.getAbsolutePath(), ProjectProperties properties = ProjectProperties.load(baseDir.getAbsolutePath(),
PropertyType.DEFAULT); PropertyType.DEFAULT);
@@ -211,9 +218,13 @@ public class ApkBuilderTask extends Task {
if (apkConfigs.size() > 0) { if (apkConfigs.size() > 0) {
Set<Entry<String, String>> entrySet = apkConfigs.entrySet(); Set<Entry<String, String>> entrySet = apkConfigs.entrySet();
for (Entry<String, String> entry : entrySet) { for (Entry<String, String> entry : entrySet) {
createApk(apkBuilder, entry.getKey(), entry.getValue()); createApk(apkBuilder, entry.getKey(), entry.getValue(), path);
} }
} }
// finally sets the path in the project with a reference
antProject.addReference(REF_APK_PATH, path);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new BuildException(e); throw new BuildException(e);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@@ -230,10 +241,12 @@ public class ApkBuilderTask extends Task {
* package will be generated. * package will be generated.
* @param resourceFilter the resource configuration filter to pass to aapt (if configName is * @param resourceFilter the resource configuration filter to pass to aapt (if configName is
* non null) * non null)
* @param path Ant {@link Path} to which add the generated APKs as {@link PathElement}
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws ApkCreationException * @throws ApkCreationException
*/ */
private void createApk(ApkBuilderImpl apkBuilder, String configName, String resourceFilter) private void createApk(ApkBuilderImpl apkBuilder, String configName, String resourceFilter,
Path path)
throws FileNotFoundException, ApkCreationException { throws FileNotFoundException, ApkCreationException {
// All the files to be included in the archive have already been prep'ed up, except // All the files to be included in the archive have already been prep'ed up, except
// the resource package. // the resource package.
@@ -259,7 +272,7 @@ public class ApkBuilderTask extends Task {
} }
if (mSigned) { if (mSigned) {
filename = filename + "-debug.apk"; filename = filename + "-debug-unaligned.apk";
} else { } else {
filename = filename + "-unsigned.apk"; filename = filename + "-unsigned.apk";
} }
@@ -284,8 +297,13 @@ public class ApkBuilderTask extends Task {
} }
} }
// out File
File f = new File(mOutFolder, filename); File f = new File(mOutFolder, filename);
// add it to the Path object
PathElement element = path.createPathElement();
element.setLocation(f);
// and generate the apk // and generate the apk
apkBuilder.createPackage(f.getAbsoluteFile(), mZipArchives, apkBuilder.createPackage(f.getAbsoluteFile(), mZipArchives,
mArchiveFiles, mJavaResources, mResourcesJars, mNativeLibraries); mArchiveFiles, mJavaResources, mResourcesJars, mNativeLibraries);

View File

@@ -61,11 +61,16 @@
</condition> </condition>
<!-- The final package file to generate --> <!-- The final package file to generate -->
<property name="out-debug-unaligned-package" value="${out-folder}/${ant.project.name}-debug-unaligned.apk"/>
<property name="out-debug-package" value="${out-folder}/${ant.project.name}-debug.apk"/> <property name="out-debug-package" value="${out-folder}/${ant.project.name}-debug.apk"/>
<property name="out-unsigned-package" value="${out-folder}/${ant.project.name}-unsigned.apk"/>
<property name="out-unaligned-package" value="${out-folder}/${ant.project.name}-unaligned.apk"/>
<property name="out-release-package" value="${out-folder}/${ant.project.name}-release.apk"/>
<!-- Tools --> <!-- Tools -->
<condition property="exe" value=".exe" else=""><os family="windows"/></condition> <condition property="exe" value=".exe" else=""><os family="windows"/></condition>
<property name="adb" value="${android-tools}/adb${exe}"/> <property name="adb" value="${android-tools}/adb${exe}"/>
<property name="zipalign" value="${android-tools}/zipalign${exe}" />
<!-- rules --> <!-- rules -->
@@ -151,14 +156,14 @@
basename="${ant.project.name}" /> basename="${ant.project.name}" />
</target> </target>
<!-- Package the application and sign it with a debug key. <!-- Package the application and (maybe) sign it with a debug key.
This is the default target when building. It is used for debug. --> This requires the property sign.package to be set to true or false. -->
<target name="debug" depends="dex, package-resources"> <target name="package">
<apkbuilder <apkbuilder
outfolder="${out-folder}" outfolder="${out-folder}"
basename="${ant.project.name}" basename="${ant.project.name}"
signed="true" signed="${sign.package}"
verbose="false"> verbose="true">
<file path="${intermediate-dex}" /> <file path="${intermediate-dex}" />
<sourcefolder path="${source-folder}" /> <sourcefolder path="${source-folder}" />
<jarfolder path="${external-libs-folder}" /> <jarfolder path="${external-libs-folder}" />
@@ -166,20 +171,65 @@
</apkbuilder> </apkbuilder>
</target> </target>
<!-- Package the application without signing it. <target name="no-sign">
This allows for the application to be signed later with an official publishing key. --> <property name="sign.package" value="false" />
<target name="release" depends="dex, package-resources"> </target>
<apkbuilder
outfolder="${out-folder}" <target name="debug-sign">
basename="${ant.project.name}" <property name="sign.package" value="true" />
signed="false" </target>
verbose="false">
<file path="${intermediate-dex}" /> <target name="debug" depends="dex, package-resources, debug-sign, package">
<sourcefolder path="${source-folder}" /> <exec executable="${zipalign}" failonerror="true">
<jarfolder path="${external-libs-folder}" /> <arg value="-f" />
<nativefolder path="${native-libs-folder}" /> <arg value="4" />
</apkbuilder> <arg path="${out-debug-unaligned-package}" />
<echo>All generated packages need to be signed with jarsigner before they are published.</echo> <arg path="${out-debug-package}" />
</exec>
<echo>Debug Package: ${out-debug-package}</echo>
</target>
<target name="release-package" depends="dex, package-resources, no-sign, package">
</target>
<target name="release.check">
<condition property="release.sign">
<and>
<isset property="key.store" />
<isset property="key.alias" />
</and>
</condition>
</target>
<target name="release.nosign" depends="release.check" unless="release.sign">
<echo>No key.store and key.alias properties found in build.properties.</echo>
<echo>Please sign ${out-unsigned-package} manually</echo>
<echo>and run zipalign from the Android SDK tools.</echo>
</target>
<target name="release" depends="release-package, release.nosign" if="release.sign">
<!-- get passwords -->
<input
message="Please enter keystore password (store:${key.store}):"
addproperty="key.store.password"/>
<input
message="Please enter password for alias '${key.alias}':"
addproperty="key.alias.password"/>
<!-- sign the APK -->
<signjar
jar="${out-unsigned-package}"
signedjar="${out-unaligned-package}"
keystore="${key.store}"
storepass="${key.store.password}"
alias="${key.alias}"
keypass="${key.alias.password}"/>
<!-- zip align the APK -->
<exec executable="${zipalign}" failonerror="true">
<arg value="-f" />
<arg value="4" />
<arg path="${out-unaligned-package}" />
<arg path="${out-release-package}" />
</exec>
<echo>Release Package: ${out-release-package}</echo>
</target> </target>
<!-- Install the package on the default emulator --> <!-- Install the package on the default emulator -->

View File

@@ -85,9 +85,17 @@ public final class ProjectProperties {
"# This file must be checked in Version Control Systems, as it is\n" + "# This file must be checked in Version Control Systems, as it is\n" +
"# integral to the build system of your project.\n" + "# integral to the build system of your project.\n" +
"\n" + "\n" +
"# This file is only used by the Ant script.\n" +
"\n" +
"# You can use this to override default values such as\n" + "# You can use this to override default values such as\n" +
"# 'source-folder' for the location of your java source folder and\n" + "# 'source-folder' for the location of your java source folder and\n" +
"# 'out-folder' for the location of your output folder.\n" + "# 'out-folder' for the location of your output folder.\n" +
"\n" +
"# You can also use it define how the release builds are signed by declaring\n" +
"# the following properties:\n" +
"# 'key.store' for the location of your keystore and\n" +
"# 'key.alias' for the name of the key to use.\n" +
"# The password will be asked during the build when you use the 'release' target.\n" +
"\n"; "\n";
private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>(); private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();