OSDN Git Service

Android project's output for JDT is now bin/classes/
authorXavier Ducrohet <xav@android.com>
Tue, 25 Jan 2011 18:34:09 +0000 (10:34 -0800)
committerXavier Ducrohet <xav@android.com>
Tue, 19 Jul 2011 00:17:19 +0000 (17:17 -0700)
This matches the bin structure of the Ant build system where
the javac output is in bin/classes/ and the Android specific files
are in bin/
Also, this will allow us better control of android output files
as they won't conflict with javac's output.

New projects are created with this setup and existing projects
are converted as they are opened.

Change-Id: I83339906b0d43d7a988a75927c60b664c183d27f

eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/MultiApkExportAction.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/FolderDecorator.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ProjectCheckPage.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java

index cdf48ad..3125c89 100644 (file)
@@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.internal.actions;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.AndroidPrintStream;
 import com.android.ide.eclipse.adt.internal.build.BuildHelper;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
 import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
 import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
@@ -277,19 +278,20 @@ public class MultiApkExportAction implements IObjectActionDelegate {
 
             // get the manifest file
             IFile manifestFile = project.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML);
-            // get the project bin folder
-            IFolder projectBinFolder = wsRoot.getFolder(javaProject.getOutputLocation());
-            String projectBinFolderPath = projectBinFolder.getLocation().toOSString();
+
+            // get the project bin folder for android files.
+            IFolder androidBinFolder = BaseProjectHelper.getAndroidOutputFolder(project);
+            String androidBinFolderPath = androidBinFolder.getLocation().toOSString();
 
             // package the resources
             helper.packageResources(manifestFile, libProjects,
                     softVariant != null ? softVariant.getValue() : null,
-                    compositeVersionCode, projectBinFolderPath, pkgName);
+                    compositeVersionCode, androidBinFolderPath, pkgName);
 
             apk.setOutputName(softVariant != null ? softVariant.getKey() : null, outputName);
 
             // do the final export.
-            IFile dexFile = projectBinFolder.getFile(SdkConstants.FN_APK_CLASSES_DEX);
+            IFile dexFile = androidBinFolder.getFile(SdkConstants.FN_APK_CLASSES_DEX);
             String outputFile = binFolder.getFile(outputName).getLocation().toOSString();
 
             // get the list of referenced projects.
@@ -297,7 +299,7 @@ public class MultiApkExportAction implements IObjectActionDelegate {
             List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaRefs);
 
             helper.finalPackage(
-                    new File(projectBinFolderPath, pkgName).getAbsolutePath(),
+                    new File(androidBinFolderPath, pkgName).getAbsolutePath(),
                     dexFile.getLocation().toOSString(),
                     outputFile,
                     javaProject,
index 5aa9647..2ce98e0 100644 (file)
@@ -364,8 +364,13 @@ public class BuildHelper {
         }
     }
 
-    public String[] getProjectOutputs() throws CoreException {
-        IFolder outputFolder = BaseProjectHelper.getOutputFolder(mProject);
+    /**
+     * Return a list of the project output for compiled Java code.
+     * @return
+     * @throws CoreException
+     */
+    public String[] getProjectJavaOutputs() throws CoreException {
+        IFolder outputFolder = BaseProjectHelper.getJavaOutputFolder(mProject);
 
         // get the list of referenced projects output to add
         List<IProject> javaProjects = ProjectHelper.getReferencedProjects(mProject);
@@ -373,7 +378,7 @@ public class BuildHelper {
 
         // get the project output, and since it's a new list object, just add the outputFolder
         // of the project directly to it.
-        List<String> projectOutputs = getProjectOutputs(referencedJavaProjects);
+        List<String> projectOutputs = getProjectJavaOutputs(referencedJavaProjects);
 
         projectOutputs.add(0, outputFolder.getLocation().toOSString());
 
@@ -403,7 +408,7 @@ public class BuildHelper {
         String[] compiledPaths;
 
         if (includeProjectOutputs) {
-            String[] projectOutputs = getProjectOutputs();
+            String[] projectOutputs = getProjectJavaOutputs();
 
             compiledPaths = new String[libraries.length + projectOutputs.length];
 
@@ -964,7 +969,7 @@ public class BuildHelper {
      * @return a new list object containing the output folder paths.
      * @throws CoreException
      */
-    private List<String> getProjectOutputs(List<IJavaProject> referencedJavaProjects)
+    private List<String> getProjectJavaOutputs(List<IJavaProject> referencedJavaProjects)
             throws CoreException {
         ArrayList<String> list = new ArrayList<String>();
 
index 1770df9..4b408e6 100644 (file)
@@ -23,10 +23,10 @@ import com.android.ide.eclipse.adt.internal.build.AaptExecException;
 import com.android.ide.eclipse.adt.internal.build.AaptParser;
 import com.android.ide.eclipse.adt.internal.build.AaptResultException;
 import com.android.ide.eclipse.adt.internal.build.BuildHelper;
-import com.android.ide.eclipse.adt.internal.build.BuildHelper.ResourceMarker;
 import com.android.ide.eclipse.adt.internal.build.DexException;
 import com.android.ide.eclipse.adt.internal.build.Messages;
 import com.android.ide.eclipse.adt.internal.build.NativeLibInJarException;
+import com.android.ide.eclipse.adt.internal.build.BuildHelper.ResourceMarker;
 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
 import com.android.ide.eclipse.adt.internal.project.ApkInstallManager;
@@ -116,7 +116,6 @@ public class PostCompilerBuilder extends BaseBuilder {
                 mOutputFolder = javaProject.getOutputLocation();
                 mSourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
             } catch (JavaModelException e) {
-            } finally {
             }
         }
 
@@ -203,6 +202,20 @@ public class PostCompilerBuilder extends BaseBuilder {
         // Clear the project of the generic markers
         removeMarkersFromContainer(project, AdtConstants.MARKER_AAPT_PACKAGE);
         removeMarkersFromContainer(project, AdtConstants.MARKER_PACKAGING);
+
+        // also remove the files in the output folder (but not the Eclipse output folder).
+        IFolder javaOutput = BaseProjectHelper.getJavaOutputFolder(project);
+        IFolder androidOutput = BaseProjectHelper.getAndroidOutputFolder(project);
+
+        if (javaOutput.equals(androidOutput) == false) {
+            // get the content
+            IResource[] members = androidOutput.members();
+            for (IResource member : members) {
+                if (member.equals(javaOutput) == false) {
+                    member.delete(true /*force*/, monitor);
+                }
+            }
+        }
     }
 
     // build() returns a list of project from which this project depends for future compilation.
@@ -245,9 +258,8 @@ public class PostCompilerBuilder extends BaseBuilder {
             // Top level check to make sure the build can move forward.
             abortOnBadSetup(javaProject);
 
-            // get the output folder, this method returns the path with a trailing
-            // separator
-            IFolder outputFolder = BaseProjectHelper.getOutputFolder(project);
+            // get the android output folder
+            IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project);
 
             // now we need to get the classpath list
             List<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject);
@@ -276,7 +288,7 @@ public class PostCompilerBuilder extends BaseBuilder {
                     mConvertToDex = true;
                     mBuildFinalPackage = true;
                 } else {
-                    dv = new PostCompilerDeltaVisitor(this, sourceList, outputFolder);
+                    dv = new PostCompilerDeltaVisitor(this, sourceList, androidOutputFolder);
                     delta.accept(dv);
 
                     // save the state
@@ -342,7 +354,7 @@ public class PostCompilerBuilder extends BaseBuilder {
             // remove older packaging markers.
             removeMarkersFromContainer(javaProject.getProject(), AdtConstants.MARKER_PACKAGING);
 
-            if (outputFolder == null) {
+            if (androidOutputFolder == null) {
                 // mark project and exit
                 markProject(AdtConstants.MARKER_PACKAGING, Messages.Failed_To_Get_Output,
                         IMarker.SEVERITY_ERROR);
@@ -377,7 +389,7 @@ public class PostCompilerBuilder extends BaseBuilder {
 
             if (mPackageResources == false) {
                 // check the full resource package
-                tmp = outputFolder.findMember(AdtConstants.FN_RESOURCES_AP_);
+                tmp = androidOutputFolder.findMember(AdtConstants.FN_RESOURCES_AP_);
                 if (tmp == null || tmp.exists() == false) {
                     mPackageResources = true;
                     mBuildFinalPackage = true;
@@ -386,7 +398,7 @@ public class PostCompilerBuilder extends BaseBuilder {
 
             // check classes.dex is present. If not we force to recreate it.
             if (mConvertToDex == false) {
-                tmp = outputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX);
+                tmp = androidOutputFolder.findMember(SdkConstants.FN_APK_CLASSES_DEX);
                 if (tmp == null || tmp.exists() == false) {
                     mConvertToDex = true;
                     mBuildFinalPackage = true;
@@ -396,7 +408,7 @@ public class PostCompilerBuilder extends BaseBuilder {
             // also check the final file(s)!
             String finalPackageName = ProjectHelper.getApkFilename(project, null /*config*/);
             if (mBuildFinalPackage == false) {
-                tmp = outputFolder.findMember(finalPackageName);
+                tmp = androidOutputFolder.findMember(finalPackageName);
                 if (tmp == null || (tmp instanceof IFile &&
                         tmp.exists() == false)) {
                     String msg = String.format(Messages.s_Missing_Repackaging, finalPackageName);
@@ -410,7 +422,7 @@ public class PostCompilerBuilder extends BaseBuilder {
             // because they are missing
 
             // refresh the output directory first
-            IContainer ic = outputFolder.getParent();
+            IContainer ic = androidOutputFolder.getParent();
             if (ic != null) {
                 ic.refreshLocal(IResource.DEPTH_ONE, monitor);
             }
@@ -443,18 +455,18 @@ public class PostCompilerBuilder extends BaseBuilder {
                     return allRefProjects;
                 }
 
-                IPath binLocation = outputFolder.getLocation();
-                if (binLocation == null) {
+                IPath androidBinLocation = androidOutputFolder.getLocation();
+                if (androidBinLocation == null) {
                     markProject(AdtConstants.MARKER_PACKAGING, Messages.Output_Missing,
                             IMarker.SEVERITY_ERROR);
                     return allRefProjects;
                 }
-                String osBinPath = binLocation.toOSString();
+                String osAndroidBinPath = androidBinLocation.toOSString();
 
                 // Remove the old .apk.
                 // This make sure that if the apk is corrupted, then dx (which would attempt
                 // to open it), will not fail.
-                String osFinalPackagePath = osBinPath + File.separator + finalPackageName;
+                String osFinalPackagePath = osAndroidBinPath + File.separator + finalPackageName;
                 File finalPackage = new File(osFinalPackagePath);
 
                 // if delete failed, this is not really a problem, as the final package generation
@@ -469,7 +481,7 @@ public class PostCompilerBuilder extends BaseBuilder {
 
                     try {
                         helper.packageResources(manifestFile, libProjects, null /*resfilter*/,
-                                0 /*versionCode */, osBinPath,
+                                0 /*versionCode */, osAndroidBinPath,
                                 AdtConstants.FN_RESOURCES_AP_);
                     } catch (AaptExecException e) {
                         BaseProjectHelper.markResource(project, AdtConstants.MARKER_PACKAGING,
@@ -501,14 +513,16 @@ public class PostCompilerBuilder extends BaseBuilder {
                     saveProjectBooleanProperty(PROPERTY_PACKAGE_RESOURCES, mPackageResources);
                 }
 
+                String classesDexPath = osAndroidBinPath + File.separator +
+                        SdkConstants.FN_APK_CLASSES_DEX;
+
                 // then we check if we need to package the .class into classes.dex
                 if (mConvertToDex) {
                     try {
                         String[] dxInputPaths = helper.getCompiledCodePaths(
                                 true /*includeProjectOutputs*/, mResourceMarker);
 
-                        helper.executeDx(javaProject, dxInputPaths, osBinPath + File.separator +
-                                SdkConstants.FN_APK_CLASSES_DEX);
+                        helper.executeDx(javaProject, dxInputPaths, classesDexPath);
                     } catch (DexException e) {
                         String message = e.getMessage();
 
@@ -539,11 +553,9 @@ public class PostCompilerBuilder extends BaseBuilder {
                 // and classes.dex.
                 // This is the default package with all the resources.
 
-                String classesDexPath = osBinPath + File.separator +
-                        SdkConstants.FN_APK_CLASSES_DEX;
                 try {
                     helper.finalDebugPackage(
-                        osBinPath + File.separator + AdtConstants.FN_RESOURCES_AP_,
+                            osAndroidBinPath + File.separator + AdtConstants.FN_RESOURCES_AP_,
                         classesDexPath, osFinalPackagePath,
                         javaProject, libProjects, referencedJavaProjects, mResourceMarker);
                 } catch (KeytoolException e) {
@@ -602,7 +614,7 @@ public class PostCompilerBuilder extends BaseBuilder {
                 // we are done.
 
                 // get the resource to bin
-                outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor);
+                androidOutputFolder.refreshLocal(IResource.DEPTH_ONE, monitor);
 
                 // build has been done. reset the state of the builder
                 mBuildFinalPackage = false;
index 8c4d08d..84f98a3 100644 (file)
@@ -444,13 +444,14 @@ public final class BaseProjectHelper {
     }
 
     /**
-     * Returns the {@link IFolder} representing the output for the project.
+     * Returns the {@link IFolder} representing the output for the project for Android specific
+     * files.
      * <p>
      * The project must be a java project and be opened, or the method will return null.
      * @param project the {@link IProject}
      * @return an IFolder item or null.
      */
-    public final static IFolder getOutputFolder(IProject project) {
+    public final static IFolder getJavaOutputFolder(IProject project) {
         try {
             if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
                 // get a java project from the normal project object
@@ -470,4 +471,42 @@ public final class BaseProjectHelper {
         }
         return null;
     }
+
+    /**
+     * Returns the {@link IFolder} representing the output for the project for compiled Java
+     * files.
+     * <p>
+     * The project must be a java project and be opened, or the method will return null.
+     * @param project the {@link IProject}
+     * @return an IFolder item or null.
+     */
+    public final static IFolder getAndroidOutputFolder(IProject project) {
+        try {
+            if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
+                // get a java project from the normal project object
+                IJavaProject javaProject = JavaCore.create(project);
+
+                IPath path = javaProject.getOutputLocation();
+                IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+                IResource outputResource = wsRoot.findMember(path);
+
+                if (outputResource != null) { // really shouldn't happen
+                    // if the output folder is directly a child of the project,
+                    // then use it directly.
+                    if (outputResource.getParent().equals(project)) {
+                        return (IFolder) outputResource;
+                    }
+
+                    // otherwise returns the parent folder of the java output folder.
+                    return (IFolder) outputResource.getParent();
+                }
+            }
+        } catch (JavaModelException e) {
+            // Let's do nothing and return null
+        } catch (CoreException e) {
+            // Let's do nothing and return null
+        }
+        return null;
+    }
+
 }
index f531667..020d1bc 100644 (file)
@@ -34,18 +34,15 @@ import com.android.sdklib.internal.project.ProjectProperties;
 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.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.FileDialog;
@@ -160,7 +157,7 @@ public final class ExportHelper {
 
             if (runProguard) {
                 // the output of the main project (and any java-only project dependency)
-                String[] projectOutputs = helper.getProjectOutputs();
+                String[] projectOutputs = helper.getProjectJavaOutputs();
 
                 // create a jar from the output of these projects
                 File inputJar = File.createTempFile(TEMP_PREFIX, AdtConstants.DOT_JAR);
@@ -268,64 +265,44 @@ public final class ExportHelper {
     public static void exportUnsignedReleaseApk(final IProject project) {
         Shell shell = Display.getCurrent().getActiveShell();
 
-        // get the java project to get the output directory
-        IFolder outputFolder = BaseProjectHelper.getOutputFolder(project);
-        if (outputFolder != null) {
-            IPath binLocation = outputFolder.getLocation();
+        // create a default file name for the apk.
+        String fileName = project.getName() + AdtConstants.DOT_ANDROID_PACKAGE;
 
-            // make the full path to the package
-            String fileName = project.getName() + AdtConstants.DOT_ANDROID_PACKAGE;
+        // Pop up the file save window to get the file location
+        FileDialog fileDialog = new FileDialog(shell, SWT.SAVE);
 
-            File file = new File(binLocation.toOSString() + File.separator + fileName);
+        fileDialog.setText("Export Project");
+        fileDialog.setFileName(fileName);
 
-            if (file.exists() == false || file.isFile() == false) {
-                MessageDialog.openError(Display.getCurrent().getActiveShell(),
-                        "Android IDE Plug-in",
-                        String.format("Failed to export %1$s: %2$s doesn't exist!",
-                                project.getName(), file.getPath()));
-                return;
-            }
-
-            // ok now pop up the file save window
-            FileDialog fileDialog = new FileDialog(shell, SWT.SAVE);
-
-            fileDialog.setText("Export Project");
-            fileDialog.setFileName(fileName);
-
-            final String saveLocation = fileDialog.open();
-            if (saveLocation != null) {
-                new Job("Android Release Export") {
-                    @Override
-                    protected IStatus run(IProgressMonitor monitor) {
-                        try {
-                            exportReleaseApk(project,
-                                    new File(saveLocation),
-                                    null, //key
-                                    null, //certificate
-                                    monitor);
-
-                            // this is unsigned export. Let's tell the developers to run zip align
-                            AdtPlugin.displayWarning("Android IDE Plug-in", String.format(
-                                    "An unsigned package of the application was saved at\n%1$s\n\n" +
-                                    "Before publishing the application you will need to:\n" +
-                                    "- Sign the application with your release key,\n" +
-                                    "- run zipalign on the signed package. ZipAlign is located in <SDK>/tools/\n\n" +
-                                    "Aligning applications allows Android to use application resources\n" +
-                                    "more efficiently.", saveLocation));
-
-                            return Status.OK_STATUS;
-                        } catch (CoreException e) {
-                            AdtPlugin.displayError("Android IDE Plug-in", String.format(
-                                    "Error exporting application:\n\n%1$s", e.getMessage()));
-                            return e.getStatus();
-                        }
+        final String saveLocation = fileDialog.open();
+        if (saveLocation != null) {
+            new Job("Android Release Export") {
+                @Override
+                protected IStatus run(IProgressMonitor monitor) {
+                    try {
+                        exportReleaseApk(project,
+                                new File(saveLocation),
+                                null, //key
+                                null, //certificate
+                                monitor);
+
+                        // this is unsigned export. Let's tell the developers to run zip align
+                        AdtPlugin.displayWarning("Android IDE Plug-in", String.format(
+                                "An unsigned package of the application was saved at\n%1$s\n\n" +
+                                "Before publishing the application you will need to:\n" +
+                                "- Sign the application with your release key,\n" +
+                                "- run zipalign on the signed package. ZipAlign is located in <SDK>/tools/\n\n" +
+                                "Aligning applications allows Android to use application resources\n" +
+                                "more efficiently.", saveLocation));
+
+                        return Status.OK_STATUS;
+                    } catch (CoreException e) {
+                        AdtPlugin.displayError("Android IDE Plug-in", String.format(
+                                "Error exporting application:\n\n%1$s", e.getMessage()));
+                        return e.getStatus();
                     }
-                }.schedule();
-            }
-        } else {
-            MessageDialog.openError(shell, "Android IDE Plug-in",
-                    String.format("Failed to export %1$s: Could not get project output location",
-                            project.getName()));
+                }
+            }.schedule();
         }
     }
 
index 394338b..4fd3c35 100644 (file)
@@ -16,8 +16,8 @@
 
 package com.android.ide.eclipse.adt.internal.project;
 
-import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.sdklib.SdkConstants;
 
@@ -66,6 +66,8 @@ public class FolderDecorator implements ILightweightLabelDecorator {
                             doDecoration(decoration, " [Generated Java Files]");
                         } else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
                             doDecoration(decoration, null);
+                        } else if (name.equals(SdkConstants.FD_OUTPUT)) {
+                            doDecoration(decoration, null);
                         } else if (folder.isLinked() && Sdk.CREATOR_ADT.equals(
                                 ProjectHelper.loadStringProperty(folder, Sdk.PROP_CREATOR))) {
                             doDecoration(decoration, " [Android Library]");
index 97dd68e..2804bac 100644 (file)
@@ -772,7 +772,7 @@ public final class ProjectHelper {
      */
     public static IFile getApplicationPackage(IProject project) {
         // get the output folder
-        IFolder outputLocation = BaseProjectHelper.getOutputFolder(project);
+        IFolder outputLocation = BaseProjectHelper.getAndroidOutputFolder(project);
 
         if (outputLocation == null) {
             AdtPlugin.printErrorToConsole(project,
index 33d49a8..e704c05 100644 (file)
@@ -838,6 +838,40 @@ public final class Sdk  {
                 // of which can happen here since we're processing a Project opened event.
             }
 
+            // convert older projects which use bin as the eclipse output folder into projects
+            // using bin/classes
+            IFolder javaOutput = BaseProjectHelper.getJavaOutputFolder(openedProject);
+            IFolder androidOutput = BaseProjectHelper.getAndroidOutputFolder(openedProject);
+            if (javaOutput.equals(androidOutput)) {
+                final IFolder newJavaOutput = javaOutput.getFolder(SdkConstants.FD_CLASSES_OUTPUT);
+                if (newJavaOutput.exists() == false) {
+                    Job job = new Job("Project bin convertion") {
+                        @Override
+                        protected IStatus run(IProgressMonitor monitor) {
+                            try {
+                                newJavaOutput.create(true /*force*/, true /*local*/,
+                                        monitor);
+
+                                // set the java output to this project.
+                                IJavaProject javaProject = JavaCore.create(openedProject);
+                                javaProject.setOutputLocation(newJavaOutput.getFullPath(),
+                                        monitor);
+
+                                openedProject.build(IncrementalProjectBuilder.CLEAN_BUILD, monitor);
+                            } catch (CoreException e) {
+                                return e.getStatus();
+                            }
+
+                            return Status.OK_STATUS;
+                        }
+                    };
+                    job.setPriority(Job.BUILD); // build jobs are run after other interactive jobs
+                    job.schedule();
+
+                }
+            }
+
+
             ProjectState openedState = getProjectState(openedProject);
             if (openedState != null) {
                 if (openedState.hasLibraries()) {
index f7978fb..9ebdfbb 100644 (file)
@@ -40,7 +40,6 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
 
@@ -55,7 +54,6 @@ final class ProjectCheckPage extends ExportWizardPage {
     private final static String IMG_WARNING = "warning.png"; //$NON-NLS-1$
 
     private final ExportWizard mWizard;
-    private Display mDisplay;
     private Image mError;
     private Image mWarning;
     private boolean mHasMessage = false;
@@ -76,7 +74,6 @@ final class ProjectCheckPage extends ExportWizardPage {
     public void createControl(Composite parent) {
         mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(),
                 new NonLibraryProjectOnlyFilter());
-        mDisplay = parent.getDisplay();
 
         GridLayout gl = null;
         GridData gd = null;
@@ -170,27 +167,12 @@ final class ProjectCheckPage extends ExportWizardPage {
                     }
 
                     // check the project output
-                    IFolder outputIFolder = BaseProjectHelper.getOutputFolder(project);
-                    if (outputIFolder != null) {
-                        String outputOsPath =  outputIFolder.getLocation().toOSString();
-                        String apkFilePath =  outputOsPath + File.separator + project.getName() +
-                                AdtConstants.DOT_ANDROID_PACKAGE;
-
-                        File f = new File(apkFilePath);
-                        try {
-                            f.createNewFile();
-                        } catch (IOException e) {
-                            addError(mErrorComposite,
-                                     String.format("Could not open %1$s/%2$s/%1$s%3$s for writing!",
-                                                   project.getName(), outputIFolder.getName(),
-                                                   AdtConstants.DOT_ANDROID_PACKAGE));
-                        }
-                    } else {
+                    IFolder outputIFolder = BaseProjectHelper.getJavaOutputFolder(project);
+                    if (outputIFolder == null) {
                         addError(mErrorComposite,
                                 "Unable to get the output folder of the project!");
                     }
 
-
                     // project is an android project, we check the debuggable attribute.
                     ManifestData manifestData = AndroidManifestHelper.parseForData(project);
                     Boolean debuggable = null;
index 9a3f572..6489616 100644 (file)
@@ -136,6 +136,9 @@ public class NewProjectWizard extends Wizard implements INewWizard {
 
     private static final String BIN_DIRECTORY =
         SdkConstants.FD_OUTPUT + AdtConstants.WS_SEP;
+    private static final String BIN_CLASSES_DIRECTORY =
+        SdkConstants.FD_OUTPUT + AdtConstants.WS_SEP +
+        SdkConstants.FD_CLASSES_OUTPUT + AdtConstants.WS_SEP;
     private static final String RES_DIRECTORY =
         SdkConstants.FD_RESOURCES + AdtConstants.WS_SEP;
     private static final String ASSETS_DIRECTORY =
@@ -190,7 +193,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
     private static final String STRING_HELLO_WORLD = "hello";       //$NON-NLS-1$
 
     private static final String[] DEFAULT_DIRECTORIES = new String[] {
-            BIN_DIRECTORY, RES_DIRECTORY, ASSETS_DIRECTORY };
+            BIN_DIRECTORY, BIN_CLASSES_DIRECTORY, RES_DIRECTORY, ASSETS_DIRECTORY };
     private static final String[] RES_DIRECTORIES = new String[] {
             DRAWABLE_DIRECTORY, LAYOUT_DIRECTORY, VALUES_DIRECTORY };
     private static final String[] RES_DENSITY_ENABLED_DIRECTORIES = new String[] {
@@ -706,7 +709,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
                     monitor);
 
             // Set output location
-            javaProject.setOutputLocation(project.getFolder(BIN_DIRECTORY).getFullPath(),
+            javaProject.setOutputLocation(project.getFolder(BIN_CLASSES_DIRECTORY).getFullPath(),
                     monitor);
         }
 
index 8f5b69c..713e8a8 100644 (file)
@@ -182,6 +182,8 @@ public final class SdkConstants {
     public final static String FD_APK_NATIVE_LIBS = "lib"; //$NON-NLS-1$
     /** Default output folder name, i.e. "bin" */
     public final static String FD_OUTPUT = "bin"; //$NON-NLS-1$
+    /** Classes output folder name, i.e. "classes" */
+    public final static String FD_CLASSES_OUTPUT = "classes"; //$NON-NLS-1$
     /** proguard output folder for mapping, etc.. files */
     public final static String FD_PROGUARD = "proguard"; //$NON-NLS-1$