diff options
6 files changed, 110 insertions, 23 deletions
diff --git a/anttasks/src/com/android/ant/ApkBuilderTask.java b/anttasks/src/com/android/ant/ApkBuilderTask.java index 0d9b8fb..3f8dec1 100644 --- a/anttasks/src/com/android/ant/ApkBuilderTask.java +++ b/anttasks/src/com/android/ant/ApkBuilderTask.java @@ -39,7 +39,8 @@ public class ApkBuilderTask extends Task { private String mApkFilepath; private String mResourceFile; private boolean mVerbose = false; - private boolean mDebug = false; + private boolean mDebugPackaging = false; + private boolean mDebugSigning = false; private boolean mHasCode = true; private String mAbiFilter = null; @@ -89,7 +90,26 @@ public class ApkBuilderTask extends Task { * @param debug the debug mode value. */ public void setDebug(boolean debug) { - mDebug = debug; + System.out.println("WARNNG: Using deprecated 'debug' attribute in ApkBuilderTask." + + "Use 'debugpackaging' and 'debugsigning' instead."); + mDebugPackaging = debug; + mDebugSigning = debug; + } + + /** + * Sets the value of the "debugpackaging" attribute. + * @param debug the debug mode value. + */ + public void setDebugpackaging(boolean debug) { + mDebugPackaging = debug; + } + + /** + * Sets the value of the "debugsigning" attribute. + * @param debug the debug mode value. + */ + public void setDebugsigning(boolean debug) { + mDebugSigning = debug; } /** @@ -216,7 +236,7 @@ public class ApkBuilderTask extends Task { } try { - if (mDebug) { + if (mDebugSigning) { System.out.println(String.format( "Creating %s and signing it with a debug key...", outputFile.getName())); } else { @@ -228,9 +248,9 @@ public class ApkBuilderTask extends Task { outputFile, new File(mOutFolder, mResourceFile), dexFile, - mDebug ? ApkBuilder.getDebugKeystore() : null, + mDebugSigning ? ApkBuilder.getDebugKeystore() : null, mVerbose ? System.out : null); - apkBuilder.setDebugMode(mDebug); + apkBuilder.setDebugMode(mDebugPackaging); // add the content of the zip files. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java index ee5b850..ca1bef0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java @@ -22,10 +22,14 @@ import com.android.ide.eclipse.adt.AndroidPrintStream; import com.android.ide.eclipse.adt.internal.build.BuildHelper; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.ide.eclipse.adt.io.IFileWrapper; import com.android.sdklib.SdkConstants; +import com.android.sdklib.xml.AndroidManifest; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -48,7 +52,7 @@ import java.security.PrivateKey; import java.security.cert.X509Certificate; /** - * Export helper for project. + * Export helper to export release version of APKs. */ public final class ExportHelper { @@ -60,7 +64,7 @@ public final class ExportHelper { * @param certificate the certificate used for signing. Can be null. * @param monitor */ - public static void export(IProject project, File outputFile, PrivateKey key, + public static void exportReleaseApk(IProject project, File outputFile, PrivateKey key, X509Certificate certificate, IProgressMonitor monitor) throws CoreException { // the export, takes the output of the precompiler & Java builders so it's @@ -75,6 +79,17 @@ public final class ExportHelper { } try { + // check if the manifest declares debuggable as true. While this is a release build, + // debuggable in the manifest will override this and generate a debug build + IResource manifestResource = project.findMember(SdkConstants.FN_ANDROID_MANIFEST_XML); + if (manifestResource.getType() != IResource.FILE) { + new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, + String.format("%1$s missing.", SdkConstants.FN_ANDROID_MANIFEST_XML))); + } + + IFileWrapper manifestFile = new IFileWrapper((IFile) manifestResource); + boolean debugMode = AndroidManifest.getDebuggable(manifestFile); + AndroidPrintStream fakeStream = new AndroidPrintStream(null, null, new OutputStream() { @Override public void write(int b) throws IOException { @@ -84,7 +99,7 @@ public final class ExportHelper { BuildHelper helper = new BuildHelper(project, fakeStream, fakeStream, - false /*debugMode*/, false /*verbose*/); + debugMode, false /*verbose*/); // get the list of library projects ProjectState projectState = Sdk.getProjectState(project); @@ -186,7 +201,7 @@ public final class ExportHelper { @Override protected IStatus run(IProgressMonitor monitor) { try { - export(project, + exportReleaseApk(project, new File(saveLocation), null, //key null, //certificate diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java index 31a68e8..4a2a77a 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java @@ -287,7 +287,8 @@ public final class ExportWizard extends Wizard implements IExportWizard { } // export the signed apk. - ExportHelper.export(mProject, apkExportFile, mPrivateKey, mCertificate, monitor); + ExportHelper.exportReleaseApk(mProject, apkExportFile, + mPrivateKey, mCertificate, monitor); // align if we can if (runZipAlign) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java index d91113d..052fc50 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java @@ -198,7 +198,9 @@ final class ProjectCheckPage extends ExportWizardPage { if (debuggable != null && debuggable == Boolean.TRUE) { addWarning(mErrorComposite, - "The manifest 'debuggable' attribute is set to true.\nYou should set it to false for applications that you release to the public."); + "The manifest 'debuggable' attribute is set to true.\n" + + "You should set it to false for applications that you release to the public.\n\n" + + "Applications with debuggable=true are compiled in debug mode always."); } // check for mapview stuff diff --git a/files/ant/main_rules.xml b/files/ant/main_rules.xml index 192bd94..83f2a63 100644 --- a/files/ant/main_rules.xml +++ b/files/ant/main_rules.xml @@ -211,7 +211,8 @@ outfolder="${out.absolute.dir}" resourcefile="${resource.package.file.name}" apkfilepath="@{output.filepath}" - debug="${build.debug}" + debugpackaging="${build.packaging.debug}" + debugsigning="${build.signing.debug}" abifilter="${filter.abi}" verbose="${verbose}" hascode="${manifest.hasCode}"> @@ -449,7 +450,7 @@ <aapt executable="${aapt}" command="package" versioncode="${version.code}" - debug="${build.debug}" + debug="${build.packaging.debug}" manifest="AndroidManifest.xml" assets="${asset.absolute.dir}" androidjar="${android.jar}" @@ -492,7 +493,11 @@ <property name="build.mode.debug" value="true"/> <!-- whether the build is a debug build. always set. --> - <property name="build.debug" value="true" /> + <property name="build.packaging.debug" value="true" /> + + <!-- signing mode: debug --> + <property name="build.signing.debug" value="true" /> + </target> <!-- Builds debug output package, provided all the necessary files are already dexed --> @@ -525,25 +530,44 @@ <target name="-release-obfuscation-check"> <condition property="proguard.enabled" value="true" else="false"> - <isset property="proguard.config" /> + <and> + <isset property="build.mode.release" /> + <isset property="proguard.config" /> + </and> </condition> </target> - <target name="-set-release-mode" depends="-release-obfuscation-check"> - <!-- property only set in release mode. - Useful for if/unless attributes in target node - when using Ant before 1.8 --> - <property name="build.mode.release" value="true"/> + <target name="-set-release-mode"> + <!-- release mode is only valid if the manifest does not explicitly + set debuggable to true. default is false. + We actually store build.packaging.debug, not build.release --> + <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:debuggable" + output="build.packaging.debug" default="false"/> - <!-- whether the build is a debug build. always set. --> - <property name="build.debug" value="false" /> + <!-- signing mode: release --> + <property name="build.signing.debug" value="false" /> + + <if condition="${build.packaging.debug}"> + <then> + <echo>*************************************************</echo> + <echo>**** Android Manifest has debuggable=true ****</echo> + <echo>**** Doing DEBUG packaging with RELEASE keys ****</echo> + <echo>*************************************************</echo> + </then> + <else> + <!-- property only set in release mode. + Useful for if/unless attributes in target node + when using Ant before 1.8 --> + <property name="build.mode.release" value="true"/> + </else> + </if> </target> <!-- This runs -package-release and -release-nosign first and then runs only if release-sign is true (set in -release-check, called by -release-no-sign)--> <target name="release" - depends="-set-release-mode, -package-release, -release-prompt-for-password, -release-nosign" + depends="-set-release-mode, -release-obfuscation-check, -package-release, -release-prompt-for-password, -release-nosign" if="has.keystore" description="Builds the application. The generated apk file must be signed before it is published."> diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java index ed07635..bfb42b1 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidManifest.java @@ -103,6 +103,31 @@ public final class AndroidManifest { } /** + * Returns whether the manifest is set to make the application debuggable. + * + * If the give manifest does not contain the debuggable attribute then the application + * is considered to not be debuggable. + * + * @param manifestFile the manifest to parse. + * @return true if the application is debuggable. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static boolean getDebuggable(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + String value = xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_APPLICATION + + "/@" + ATTRIBUTE_DEBUGGABLE, + new InputSource(manifestFile.getContents())); + + // default is not debuggable, which is the same behavior as parseBoolean + return Boolean.parseBoolean(value); + } + + /** * Returns the value of the versionCode attribute or -1 if the value is not set. * @param manifestFile the manifest file to read the attribute from. * @return the integer value or -1 if not set. |