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;
// 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.
List<IJavaProject> referencedJavaProjects = BuildHelper.getJavaProjects(javaRefs);
helper.finalPackage(
- new File(projectBinFolderPath, pkgName).getAbsolutePath(),
+ new File(androidBinFolderPath, pkgName).getAbsolutePath(),
dexFile.getLocation().toOSString(),
outputFile,
javaProject,
}
}
- 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);
// 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());
String[] compiledPaths;
if (includeProjectOutputs) {
- String[] projectOutputs = getProjectOutputs();
+ String[] projectOutputs = getProjectJavaOutputs();
compiledPaths = new String[libraries.length + projectOutputs.length];
* @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>();
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;
mOutputFolder = javaProject.getOutputLocation();
mSourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
} catch (JavaModelException e) {
- } finally {
}
}
// 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.
// 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);
mConvertToDex = true;
mBuildFinalPackage = true;
} else {
- dv = new PostCompilerDeltaVisitor(this, sourceList, outputFolder);
+ dv = new PostCompilerDeltaVisitor(this, sourceList, androidOutputFolder);
delta.accept(dv);
// save the state
// 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);
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;
// 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;
// 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);
// 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);
}
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
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,
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();
// 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) {
// 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;
}
/**
- * 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
}
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;
+ }
+
}
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;
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);
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();
}
}
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;
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]");
*/
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,
// 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()) {
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;
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;
public void createControl(Composite parent) {
mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(),
new NonLibraryProjectOnlyFilter());
- mDisplay = parent.getDisplay();
GridLayout gl = null;
GridData gd = null;
}
// 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;
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 =
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[] {
monitor);
// Set output location
- javaProject.setOutputLocation(project.getFolder(BIN_DIRECTORY).getFullPath(),
+ javaProject.setOutputLocation(project.getFolder(BIN_CLASSES_DIRECTORY).getFullPath(),
monitor);
}
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$