diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-19 10:57:29 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-19 10:57:29 -0800 |
| commit | 4fd2474506c1ea3cb96e128d72db2a18ec1e258d (patch) | |
| tree | 5457d1e4f807ae30e59b72f74d876284b20eba9d /eclipse | |
| parent | b58a893bf9ba96db9a544cd33af4828826b73061 (diff) | |
| download | sdk-4fd2474506c1ea3cb96e128d72db2a18ec1e258d.zip sdk-4fd2474506c1ea3cb96e128d72db2a18ec1e258d.tar.gz sdk-4fd2474506c1ea3cb96e128d72db2a18ec1e258d.tar.bz2 | |
auto import from //branches/cupcake/...@132276
Diffstat (limited to 'eclipse')
16 files changed, 510 insertions, 238 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index ddc93ac..9aa9354 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -20,7 +20,6 @@ import com.android.ddmuilib.StackTracePanel; import com.android.ddmuilib.StackTracePanel.ISourceRevealer; import com.android.ddmuilib.console.DdmConsole; import com.android.ddmuilib.console.IDdmConsole; -import com.android.ide.eclipse.adt.build.DexWrapper; import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController; import com.android.ide.eclipse.adt.preferences.BuildPreferencePage; import com.android.ide.eclipse.adt.project.ProjectHelper; @@ -423,8 +422,6 @@ public class AdtPlugin extends AbstractUIPlugin { stopEditors(); - DexWrapper.unloadDex(); - mRed.dispose(); synchronized (AdtPlugin.class) { sPlugin = null; @@ -465,21 +462,11 @@ public class AdtPlugin extends AbstractUIPlugin { return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_ADB; } - /** Returns the aapt path relative to the sdk folder */ - public static String getOsRelativeAapt() { - return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AAPT; - } - /** Returns the emulator path relative to the sdk folder */ public static String getOsRelativeEmulator() { return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_EMULATOR; } - /** Returns the aidl path relative to the sdk folder */ - public static String getOsRelativeAidl() { - return SdkConstants.OS_SDK_TOOLS_FOLDER + AndroidConstants.FN_AIDL; - } - /** Returns the absolute adb path */ public static String getOsAbsoluteAdb() { return getOsSdkFolder() + getOsRelativeAdb(); @@ -491,21 +478,11 @@ public class AdtPlugin extends AbstractUIPlugin { AndroidConstants.FN_TRACEVIEW; } - /** Returns the absolute aapt path */ - public static String getOsAbsoluteAapt() { - return getOsSdkFolder() + getOsRelativeAapt(); - } - /** Returns the absolute emulator path */ public static String getOsAbsoluteEmulator() { return getOsSdkFolder() + getOsRelativeEmulator(); } - /** Returns the absolute aidl path */ - public static String getOsAbsoluteAidl() { - return getOsSdkFolder() + getOsRelativeAidl(); - } - /** * Returns a Url file path to the javaDoc folder. */ @@ -968,8 +945,6 @@ public class AdtPlugin extends AbstractUIPlugin { // check the path to various tools we use String[] filesToCheck = new String[] { osSdkLocation + getOsRelativeAdb(), - osSdkLocation + getOsRelativeAapt(), - osSdkLocation + getOsRelativeAidl(), osSdkLocation + getOsRelativeEmulator() }; for (String file : filesToCheck) { @@ -1058,17 +1033,6 @@ public class AdtPlugin extends AbstractUIPlugin { // FIXME: move this per platform, or somewhere else. progress = SubMonitor.convert(monitor, Messages.AdtPlugin_Parsing_Resources, 20); - DexWrapper.unloadDex(); - - IStatus res = DexWrapper.loadDex( - mOsSdkLocation + AndroidConstants.OS_SDK_LIBS_DX_JAR); - if (res != Status.OK_STATUS) { - synchronized (getSdkLockObject()) { - mSdkIsLoaded = LoadStatus.FAILED; - mPostLoadProjectsToResolve.clear(); - } - return res; - } synchronized (getSdkLockObject()) { mSdkIsLoaded = LoadStatus.LOADED; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java index 43971b0..c359905 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java @@ -19,7 +19,7 @@ package com.android.ide.eclipse.adt.build; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.project.ProjectHelper; -import com.android.ide.eclipse.adt.sdk.LoadStatus; +import com.android.ide.eclipse.adt.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.sdk.Sdk; import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.project.BaseProjectHelper; @@ -67,6 +67,8 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; public class ApkBuilder extends BaseBuilder { @@ -280,8 +282,12 @@ public class ApkBuilder extends BaseBuilder { } } - // also check the final file! - String finalPackageName = project.getName() + AndroidConstants.DOT_ANDROID_PACKAGE; + // get the extra configs for the project. This will give us a list of custom apk + // to build based on a restricted set of resources. + Map<String, String> configs = Sdk.getCurrent().getProjectConfigs(project); + + // also check the final file(s)! + String finalPackageName = getFileName(project, null /*config*/); if (mBuildFinalPackage == false && outputFolder != null) { tmp = outputFolder.findMember(finalPackageName); if (tmp == null || (tmp instanceof IFile && @@ -290,6 +296,24 @@ public class ApkBuilder extends BaseBuilder { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg); mBuildFinalPackage = true; } + + if (configs != null) { + Set<Entry<String, String>> entrySet = configs.entrySet(); + + for (Entry<String, String> entry : entrySet) { + String filename = getFileName(project, entry.getKey()); + + tmp = outputFolder.findMember(filename); + if (tmp == null || (tmp instanceof IFile && + tmp.exists() == false)) { + String msg = String.format(Messages.s_Missing_Repackaging, + finalPackageName); + AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg); + mBuildFinalPackage = true; + break; + } + } + } } // store the build status in the persistent storage @@ -358,6 +382,17 @@ public class ApkBuilder extends BaseBuilder { // handle already present .apk, and if that one failed as well, the user will be // notified. finalPackage.delete(); + + if (configs != null) { + Set<Entry<String, String>> entrySet = configs.entrySet(); + for (Entry<String, String> entry : entrySet) { + String packageFilepath = osBinPath + File.separator + + getFileName(project, entry.getKey()); + + finalPackage = new File(packageFilepath); + finalPackage.delete(); + } + } // first we check if we need to package the resources. if (mPackageResources) { @@ -401,13 +436,30 @@ public class ApkBuilder extends BaseBuilder { osAssetsPath = assetsFolder.getLocation().toOSString(); } + // build the default resource package if (executeAapt(project, osManifestPath, osResPath, osAssetsPath, osBinPath + File.separator + - AndroidConstants.FN_RESOURCES_AP_) == false) { + AndroidConstants.FN_RESOURCES_AP_, null /*configFilter*/) == false) { // aapt failed. Whatever files that needed to be marked // have already been marked. We just return. return referencedProjects; } + + // now do the same thing for all the configured resource packages. + if (configs != null) { + Set<Entry<String, String>> entrySet = configs.entrySet(); + for (Entry<String, String> entry : entrySet) { + String outPathFormat = osBinPath + File.separator + + AndroidConstants.FN_RESOURCES_S_AP_; + String outPath = String.format(outPathFormat, entry.getKey()); + if (executeAapt(project, osManifestPath, osResPath, + osAssetsPath, outPath, entry.getValue()) == false) { + // aapt failed. Whatever files that needed to be marked + // have already been marked. We just return. + return referencedProjects; + } + } + } // build has been done. reset the state of the builder mPackageResources = false; @@ -433,25 +485,49 @@ public class ApkBuilder extends BaseBuilder { } // now we need to make the final package from the intermediary apk - // and classes.dex + // and classes.dex. + // This is the default package with all the resources. + String classesDexPath = osBinPath + File.separator + AndroidConstants.FN_CLASSES_DEX; if (finalPackage(osBinPath + File.separator + AndroidConstants.FN_RESOURCES_AP_, - osBinPath + File.separator + AndroidConstants.FN_CLASSES_DEX, - osFinalPackagePath, javaProject, referencedJavaProjects) == false) { + classesDexPath,osFinalPackagePath, javaProject, + referencedJavaProjects) == false) { return referencedProjects; - } else { - // get the resource to bin - outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); + } + + // now do the same thing for all the configured resource packages. + if (configs != null) { + String resPathFormat = osBinPath + File.separator + + AndroidConstants.FN_RESOURCES_S_AP_; + + Set<Entry<String, String>> entrySet = configs.entrySet(); + for (Entry<String, String> entry : entrySet) { + // make the filename for the resource package. + String resPath = String.format(resPathFormat, entry.getKey()); + + // make the filename for the apk to generate + String apkOsFilePath = osBinPath + File.separator + + getFileName(project, entry.getKey()); + if (finalPackage(resPath, classesDexPath, apkOsFilePath, javaProject, + referencedJavaProjects) == false) { + return referencedProjects; + } + } + } - // build has been done. reset the state of the builder - mBuildFinalPackage = false; + // we are done. + + // get the resource to bin + outputFolder.refreshLocal(IResource.DEPTH_ONE, monitor); - // and store it - saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); - - AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), - "Build Success!"); - } + // build has been done. reset the state of the builder + mBuildFinalPackage = false; + + // and store it + saveProjectBooleanProperty(PROPERTY_BUILD_APK, mBuildFinalPackage); + + AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(), + "Build Success!"); } return referencedProjects; } @@ -475,19 +551,26 @@ public class ApkBuilder extends BaseBuilder { * @param osResPath The path to the res folder * @param osAssetsPath The path to the assets folder. This can be null. * @param osOutFilePath The path to the temporary resource file to create. + * @param configFilter The configuration filter for the resources to include + * (used with -c option) * @return true if success, false otherwise. */ private boolean executeAapt(IProject project, String osManifestPath, - String osResPath, String osAssetsPath, String osOutFilePath) { + String osResPath, String osAssetsPath, String osOutFilePath, String configFilter) { + IAndroidTarget target = Sdk.getCurrent().getTarget(project); // Create the command line. ArrayList<String> commandArray = new ArrayList<String>(); - commandArray.add(AdtPlugin.getOsAbsoluteAapt()); + commandArray.add(target.getPath(IAndroidTarget.AAPT)); commandArray.add("package"); //$NON-NLS-1$ commandArray.add("-f");//$NON-NLS-1$ if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) { commandArray.add("-v"); //$NON-NLS-1$ } + if (configFilter != null) { + commandArray.add("-c"); //$NON-NLS-1$ + commandArray.add(configFilter); + } commandArray.add("-M"); //$NON-NLS-1$ commandArray.add(osManifestPath); commandArray.add("-S"); //$NON-NLS-1$ @@ -497,8 +580,7 @@ public class ApkBuilder extends BaseBuilder { commandArray.add(osAssetsPath); } commandArray.add("-I"); //$NON-NLS-1$ - commandArray.add( - Sdk.getCurrent().getTarget(project).getPath(IAndroidTarget.ANDROID_JAR)); + commandArray.add(target.getPath(IAndroidTarget.ANDROID_JAR)); commandArray.add("-F"); //$NON-NLS-1$ commandArray.add(osOutFilePath); @@ -576,14 +658,19 @@ public class ApkBuilder extends BaseBuilder { */ private boolean executeDx(IJavaProject javaProject, String osBinPath, String osOutFilePath, IJavaProject[] referencedJavaProjects) throws CoreException { + IAndroidTarget target = Sdk.getCurrent().getTarget(javaProject.getProject()); + AndroidTargetData targetData = Sdk.getCurrent().getTargetData(target); + if (targetData == null) { + throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, + Messages.ApkBuilder_UnableBuild_Dex_Not_loaded)); + } + // get the dex wrapper - DexWrapper wrapper = DexWrapper.getWrapper(); + DexWrapper wrapper = targetData.getDexWrapper(); if (wrapper == null) { - if (DexWrapper.getStatus() == LoadStatus.FAILED) { - throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, - Messages.ApkBuilder_UnableBuild_Dex_Not_loaded)); - } + throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, + Messages.ApkBuilder_UnableBuild_Dex_Not_loaded)); } // make sure dx use the proper output streams. @@ -1003,6 +1090,19 @@ public class ApkBuilder extends BaseBuilder { return list.toArray(new IJavaProject[list.size()]); } + + /** + * Returns the apk filename for the given project + * @param project The project. + * @param config An optional config name. Can be null. + */ + private static String getFileName(IProject project, String config) { + if (config != null) { + return project.getName() + "-" + config + AndroidConstants.DOT_ANDROID_PACKAGE; //$NON-NLS-1$ + } + + return project.getName() + AndroidConstants.DOT_ANDROID_PACKAGE; + } /** * Checks a {@link IFile} to make sure it should be packaged as standard resources. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java index aec703d..5d6793a 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkDeltaVisitor.java @@ -192,11 +192,16 @@ public class ApkDeltaVisitor extends BaseDeltaVisitor IPath parentPath = path.removeLastSegments(1); if (mOutputPath.equals(parentPath)) { String resourceName = resource.getName(); + // check if classes.dex was removed if (resourceName.equalsIgnoreCase(AndroidConstants.FN_CLASSES_DEX)) { mConvertToDex = true; mMakeFinalPackage = true; } else if (resourceName.equalsIgnoreCase( - AndroidConstants.FN_RESOURCES_AP_)) { + AndroidConstants.FN_RESOURCES_AP_) || + AndroidConstants.PATTERN_RESOURCES_S_AP_.matcher( + resourceName).matches()) { + // or if the default resources.ap_ or a configured version + // (resources-###.ap_) was removed. mPackageResources = true; mMakeFinalPackage = true; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java index cba8ad7..26d96d7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/DexWrapper.java @@ -17,7 +17,6 @@ package com.android.ide.eclipse.adt.build; import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.sdk.LoadStatus; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; @@ -46,10 +45,6 @@ public final class DexWrapper { private final static String MAIN_RUN = "run"; //$NON-NLS-1$ - private static DexWrapper sWrapper; - - private static LoadStatus sLoadStatus = LoadStatus.LOADING; - private Method mRunMethod; private Constructor<?> mArgConstructor; @@ -67,10 +62,8 @@ public final class DexWrapper { * @param osFilepath the location of the dex.jar file. * @return an IStatus indicating the result of the load. */ - public static synchronized IStatus loadDex(String osFilepath) { + public synchronized IStatus loadDex(String osFilepath) { try { - sWrapper = null; - File f = new File(osFilepath); if (f.isFile() == false) { return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, String.format( @@ -86,45 +79,39 @@ public final class DexWrapper { Class<?> consoleClass = loader.loadClass(DEX_CONSOLE); Class<?> argClass = loader.loadClass(DEX_ARGS); - sWrapper = new DexWrapper(mainClass, argClass, consoleClass); - + try { + // now get the fields/methods we need + mRunMethod = mainClass.getMethod(MAIN_RUN, argClass); + + mArgConstructor = argClass.getConstructor(); + mArgOutName = argClass.getField("outName"); //$NON-NLS-1$ + mArgJarOutput = argClass.getField("jarOutput"); //$NON-NLS-1$ + mArgFileNames = argClass.getField("fileNames"); //$NON-NLS-1$ + mArgVerbose = argClass.getField("verbose"); //$NON-NLS-1$ + + mConsoleOut = consoleClass.getField("out"); //$NON-NLS-1$ + mConsoleErr = consoleClass.getField("err"); //$NON-NLS-1$ + + } catch (SecurityException e) { + return createErrorStatus(Messages.DexWrapper_SecuryEx_Unable_To_Find_API, e); + } catch (NoSuchMethodException e) { + return createErrorStatus(Messages.DexWrapper_SecuryEx_Unable_To_Find_Method, e); + } catch (NoSuchFieldException e) { + return createErrorStatus(Messages.DexWrapper_SecuryEx_Unable_To_Find_Field, e); + } + return Status.OK_STATUS; } catch (MalformedURLException e) { // really this should not happen. - return createErrorStatus(String.format(Messages.DexWrapper_Failed_to_load_s, osFilepath), e); + return createErrorStatus( + String.format(Messages.DexWrapper_Failed_to_load_s, osFilepath), e); } catch (ClassNotFoundException e) { - return createErrorStatus(String.format(Messages.DexWrapper_Failed_to_load_s, osFilepath), e); - } catch (CoreException e) { - return e.getStatus(); - } finally { - if (sWrapper == null) { - sLoadStatus = LoadStatus.FAILED; - } else { - sLoadStatus = LoadStatus.LOADED; - } + return createErrorStatus( + String.format(Messages.DexWrapper_Failed_to_load_s, osFilepath), e); } } /** - * Unloads the loaded dex wrapper. - */ - public static synchronized void unloadDex() { - sWrapper = null; - sLoadStatus = LoadStatus.LOADING; - } - - public static synchronized DexWrapper getWrapper() { - return sWrapper; - } - - /** - * Returns the {@link LoadStatus}. - */ - public static synchronized LoadStatus getStatus() { - return sLoadStatus; - } - - /** * Runs the dex command. * @param osOutFilePath the OS path to the outputfile (classes.dex * @param osFilenames list of input source files (.class and .jar files) @@ -169,33 +156,6 @@ public final class DexWrapper { } } - private DexWrapper(Class<?> mainClass, Class<?> argClass, Class<?> consoleClass) - throws CoreException { - try { - // now get the fields/methods we need - mRunMethod = mainClass.getMethod(MAIN_RUN, argClass); - - mArgConstructor = argClass.getConstructor(); - mArgOutName = argClass.getField("outName"); //$NON-NLS-1$ - mArgJarOutput = argClass.getField("jarOutput"); //$NON-NLS-1$ - mArgFileNames = argClass.getField("fileNames"); //$NON-NLS-1$ - mArgVerbose = argClass.getField("verbose"); //$NON-NLS-1$ - - mConsoleOut = consoleClass.getField("out"); //$NON-NLS-1$ - mConsoleErr = consoleClass.getField("err"); //$NON-NLS-1$ - - } catch (SecurityException e) { - throw new CoreException(createErrorStatus( - Messages.DexWrapper_SecuryEx_Unable_To_Find_API, e)); - } catch (NoSuchMethodException e) { - throw new CoreException(createErrorStatus( - Messages.DexWrapper_SecuryEx_Unable_To_Find_Method, e)); - } catch (NoSuchFieldException e) { - throw new CoreException(createErrorStatus( - Messages.DexWrapper_SecuryEx_Unable_To_Find_Field, e)); - } - } - private static IStatus createErrorStatus(String message, Exception e) { AdtPlugin.log(e, message); AdtPlugin.printErrorToConsole(Messages.DexWrapper_Dex_Loader, message); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java index 2c15d55..958cac2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java @@ -235,6 +235,7 @@ public class PreCompilerBuilder extends BaseBuilder { // get the project objects IProject project = getProject(); IJavaProject javaProject = JavaCore.create(project); + IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project); // now we need to get the classpath list ArrayList<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject); @@ -407,8 +408,6 @@ public class PreCompilerBuilder extends BaseBuilder { String osResPath = resLocation.toOSString(); String osManifestPath = manifestLocation.toOSString(); - IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project); - // remove the aapt markers removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT); removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT); @@ -432,7 +431,7 @@ public class PreCompilerBuilder extends BaseBuilder { // launch aapt: create the command line ArrayList<String> array = new ArrayList<String>(); - array.add(AdtPlugin.getOsAbsoluteAapt()); + array.add(projectTarget.getPath(IAndroidTarget.AAPT)); array.add("package"); //$NON-NLS-1$ array.add("-m"); //$NON-NLS-1$ if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) { @@ -541,7 +540,7 @@ public class PreCompilerBuilder extends BaseBuilder { if (projectAidl != null && projectAidl.exists()) { folderAidlPath = projectAidl.getLocation().toOSString(); } - boolean aidlStatus = handleAidl(sourceList, folderAidlPath, monitor); + boolean aidlStatus = handleAidl(projectTarget, sourceList, folderAidlPath, monitor); if (aidlStatus == false && mCompileResources == false) { AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, @@ -729,14 +728,15 @@ public class PreCompilerBuilder extends BaseBuilder { /** * Compiles aidl files into java. This will also removes old java files * created from aidl files that are now gone. + * @param projectTarget Target of the project * @param sourceFolders the list of source folders, relative to the workspace. * @param folderAidlPath * @param monitor the projess monitor * @returns true if it did something * @throws CoreException */ - private boolean handleAidl(ArrayList<IPath> sourceFolders, String folderAidlPath, - IProgressMonitor monitor) throws CoreException { + private boolean handleAidl(IAndroidTarget projectTarget, ArrayList<IPath> sourceFolders, + String folderAidlPath, IProgressMonitor monitor) throws CoreException { if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) { return false; } @@ -746,7 +746,7 @@ public class PreCompilerBuilder extends BaseBuilder { String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)]; int index = 0; int aidlIndex; - command[index++] = AdtPlugin.getOsAbsoluteAidl(); + command[index++] = projectTarget.getPath(IAndroidTarget.AIDL); command[aidlIndex = index++] = "-p"; //$NON-NLS-1$ if (folderAidlPath != null) { command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java index d4952b1..ac003df 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java @@ -1519,6 +1519,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(message1, launchInfo.mActivity)); } + launchInfo.mLaunch.stopLaunch(); } for (DelayedLaunchInfo launchInfo : mWaitingForDebuggerApplications) { if (launchInfo.mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING) { @@ -1527,7 +1528,11 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(message1, launchInfo.mActivity)); } + launchInfo.mLaunch.stopLaunch(); } + + mWaitingForReadyEmulatorList.clear(); + mWaitingForDebuggerApplications.clear(); } } @@ -1573,24 +1578,31 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener * * @see IDeviceChangeListener#deviceDisconnected(Device) */ + @SuppressWarnings("unchecked") public void deviceDisconnected(Device device) { // any pending launch on this device must be canceled. String message = "%1$s disconnected! Cancelling '%2$s' launch!"; synchronized (sListLock) { - for (DelayedLaunchInfo launchInfo : mWaitingForReadyEmulatorList) { + ArrayList<DelayedLaunchInfo> copyList = + (ArrayList<DelayedLaunchInfo>)mWaitingForReadyEmulatorList.clone(); + for (DelayedLaunchInfo launchInfo : copyList) { if (launchInfo.mDevice == device) { AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(message, device.getSerialNumber(), launchInfo.mActivity)); + launchInfo.mLaunch.stopLaunch(); + mWaitingForReadyEmulatorList.remove(launchInfo); } } - for (DelayedLaunchInfo launchInfo : mWaitingForDebuggerApplications) { + copyList = (ArrayList<DelayedLaunchInfo>)mWaitingForDebuggerApplications.clone(); + for (DelayedLaunchInfo launchInfo : copyList) { if (launchInfo.mDevice == device) { AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(message, device.getSerialNumber(), launchInfo.mActivity)); + launchInfo.mLaunch.stopLaunch(); + mWaitingForDebuggerApplications.remove(launchInfo); } } } - } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java index d446e2b..a260350 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java @@ -310,7 +310,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener top.setLayout(new GridLayout(1, true)); mDeviceRadioButton = new Button(top, SWT.RADIO); - mDeviceRadioButton.setText("Choose an Android running device"); + mDeviceRadioButton.setText("Choose a running Android device"); mDeviceRadioButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -387,7 +387,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener }); Button radio2 = new Button(top, SWT.RADIO); - radio2.setText("Launch a new Virtual Device"); + radio2.setText("Launch a new Android Virtual Device"); // offset the selector from the radio button offsetComp = new Composite(top, SWT.NONE); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java index 30bf7ed..339dcd0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java @@ -172,13 +172,7 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit // if we are loaded and the target is non null, we create a valid ClassPathContainer if (sdkIsLoaded && target != null) { - String targetName = null; - if (target.isPlatform()) { - targetName = target.getName(); - } else { - targetName = String.format("%1$s (%2$s)", target.getName(), - target.getApiVersionName()); - } + String targetName = target.getFullName(); return new AndroidClasspathContainer( createClasspathEntries(iProject, target, targetName), diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java index 60561ab..2309181 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetData.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt.sdk; +import com.android.ide.eclipse.adt.build.DexWrapper; import com.android.ide.eclipse.common.resources.IResourceRepository; import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider; import com.android.ide.eclipse.editors.layout.descriptors.LayoutDescriptors; @@ -54,6 +55,8 @@ public class AndroidTargetData { private final IAndroidTarget mTarget; + private DexWrapper mDexWrapper; + /** * mAttributeValues is a map { key => list [ values ] }. * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)". @@ -64,27 +67,34 @@ public class AndroidTargetData { * This is used for attributes that do not have a unique name, but still need to be populated * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}. */ - private final Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>(); + private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>(); private IResourceRepository mSystemResourceRepository; - private final AndroidManifestDescriptors mManifestDescriptors; - private final LayoutDescriptors mLayoutDescriptors; - private final MenuDescriptors mMenuDescriptors; - private final XmlDescriptors mXmlDescriptors; + private AndroidManifestDescriptors mManifestDescriptors; + private LayoutDescriptors mLayoutDescriptors; + private MenuDescriptors mMenuDescriptors; + private XmlDescriptors mXmlDescriptors; - private final Map<String, Map<String, Integer>> mEnumValueMap; + private Map<String, Map<String, Integer>> mEnumValueMap; - private final ProjectResources mFrameworkResources; - private final LayoutBridge mLayoutBridge; + private ProjectResources mFrameworkResources; + private LayoutBridge mLayoutBridge; private boolean mLayoutBridgeInit = false; + AndroidTargetData(IAndroidTarget androidTarget) { + mTarget = androidTarget; + } + + void setDexWrapper(DexWrapper wrapper) { + mDexWrapper = wrapper; + } + /** * Creates an AndroidTargetData object. */ - AndroidTargetData(IAndroidTarget androidTarget, - IResourceRepository systemResourceRepository, + void setExtraData(IResourceRepository systemResourceRepository, AndroidManifestDescriptors manifestDescriptors, LayoutDescriptors layoutDescriptors, MenuDescriptors menuDescriptors, @@ -98,7 +108,6 @@ public class AndroidTargetData { ProjectResources resources, LayoutBridge layoutBridge) { - mTarget = androidTarget; mSystemResourceRepository = systemResourceRepository; mManifestDescriptors = manifestDescriptors; mLayoutDescriptors = layoutDescriptors; @@ -113,6 +122,10 @@ public class AndroidTargetData { serviceIntentActionValues, intentCategoryValues); } + public DexWrapper getDexWrapper() { + return mDexWrapper; + } + public IResourceRepository getSystemResources() { return mSystemResourceRepository; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java index dfe876f..aab660d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/AndroidTargetParser.java @@ -17,6 +17,7 @@ package com.android.ide.eclipse.adt.sdk; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.build.DexWrapper; import com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge; import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.resources.AttrsXmlParser; @@ -91,8 +92,25 @@ public final class AndroidTargetParser { try { SubMonitor progress = SubMonitor.convert(monitor, String.format("Parsing SDK %1$s", mAndroidTarget.getName()), - 120); + 200); + AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget); + + // load DX. + DexWrapper dexWrapper = new DexWrapper(); + IStatus res = dexWrapper.loadDex(mAndroidTarget.getPath(IAndroidTarget.DX_JAR)); + if (res != Status.OK_STATUS) { + return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, + String.format("dx.jar loading failed for target '%1$s'", + mAndroidTarget.getFullName())); + } + + // we have loaded dx. + targetData.setDexWrapper(dexWrapper); + + // parse the rest of the data. + progress.setWorkRemaining(120); + AndroidJarLoader classLoader = new AndroidJarLoader(mAndroidTarget.getPath(IAndroidTarget.ANDROID_JAR)); @@ -229,8 +247,7 @@ public final class AndroidTargetParser { progress.worked(10); // and finally create the PlatformData with all that we loaded. - AndroidTargetData targetData = new AndroidTargetData(mAndroidTarget, - frameworkRepository, + targetData.setExtraData(frameworkRepository, manifestDescriptors, layoutDescriptors, menuDescriptors, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java index 01b722f..5bfa8a2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/sdk/Sdk.java @@ -18,6 +18,8 @@ package com.android.ide.eclipse.adt.sdk; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.project.internal.AndroidClasspathContainerInitializer; +import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor; +import com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISdkLog; @@ -28,6 +30,8 @@ import com.android.sdklib.project.ProjectProperties; import com.android.sdklib.project.ProjectProperties.PropertyType; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; @@ -38,6 +42,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; /** * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used @@ -48,18 +55,19 @@ import java.util.HashMap; * * To get the list of platforms or add-ons present in the SDK, call {@link #getTargets()}. */ -public class Sdk { +public class Sdk implements IProjectListener { private static Sdk sCurrentSdk = null; private final SdkManager mManager; private final AvdManager mAvdManager; - private final HashMap<IProject, IAndroidTarget> mProjectMap = + private final HashMap<IProject, IAndroidTarget> mProjectTargetMap = new HashMap<IProject, IAndroidTarget>(); - private final HashMap<IAndroidTarget, AndroidTargetData> mTargetMap = + private final HashMap<IAndroidTarget, AndroidTargetData> mTargetDataMap = new HashMap<IAndroidTarget, AndroidTargetData>(); + private final HashMap<IProject, Map<String, String>> mProjectConfigMap = + new HashMap<IProject, Map<String, String>>(); private final String mDocBaseUrl; - /** * Loads an SDK and returns an {@link Sdk} object if success. @@ -67,7 +75,7 @@ public class Sdk { */ public static Sdk loadSdk(String sdkLocation) { if (sCurrentSdk != null) { - // manual unload? + sCurrentSdk.dispose(); sCurrentSdk = null; } @@ -159,16 +167,16 @@ public class Sdk { * Associates an {@link IProject} and an {@link IAndroidTarget}. */ public void setProject(IProject project, IAndroidTarget target) { - synchronized (mProjectMap) { + synchronized (mProjectTargetMap) { // look for the current target of the project - IAndroidTarget previousTarget = mProjectMap.get(project); + IAndroidTarget previousTarget = mProjectTargetMap.get(project); if (target != previousTarget) { // save the target hash string in the project persistent property setProjectTargetHashString(project, target.hashString()); // put it in a local map for easy access. - mProjectMap.put(project, target); + mProjectTargetMap.put(project, target); // recompile the project if needed. IJavaProject javaProject = JavaCore.create(project); @@ -182,11 +190,11 @@ public class Sdk { * Returns the {@link IAndroidTarget} object associated with the given {@link IProject}. */ public IAndroidTarget getTarget(IProject project) { - synchronized (mProjectMap) { - IAndroidTarget target = mProjectMap.get(project); + synchronized (mProjectTargetMap) { + IAndroidTarget target = mProjectTargetMap.get(project); if (target == null) { // get the value from the project persistent property. - String targetHashString = getProjectTargetHashString(project); + String targetHashString = loadProjectProperties(project, this); if (targetHashString != null) { target = mManager.getTargetFromHashString(targetHashString); @@ -197,14 +205,19 @@ public class Sdk { } } + /** - * Returns the hash string uniquely identifying the target of a project. This methods reads - * the string from the project persistent preferences/properties. - * <p/>The string is equivalent to the return of {@link IAndroidTarget#hashString()}. + * Parses the project properties and returns the hash string uniquely identifying the + * target of the given project. + * <p/> + * This methods reads the content of the <code>default.properties</code> file present in + * the root folder of the project. + * <p/>The returned string is equivalent to the return of {@link IAndroidTarget#hashString()}. * @param project The project for which to return the target hash string. + * @param storeConfigs Whether the read configuration should be stored in the map. * @return the hash string or null if the project does not have a target set. */ - public static String getProjectTargetHashString(IProject project) { + private static String loadProjectProperties(IProject project, Sdk storeConfigs) { // load the default.properties from the project folder. ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString(), PropertyType.DEFAULT); @@ -214,11 +227,46 @@ public class Sdk { return null; } + if (storeConfigs != null) { + // get the list of configs. + String configList = properties.getProperty(ProjectProperties.PROPERTY_CONFIGS); + + // this is a comma separated list + String[] configs = configList.split(","); //$NON-NLS-1$ + + // read the value of each config and store it in a map + HashMap<String, String> configMap = new HashMap<String, String>(); + + for (String config : configs) { + String configValue = properties.getProperty(config); + if (configValue != null) { + configMap.put(config, configValue); + } + } + + if (configMap.size() > 0) { + storeConfigs.mProjectConfigMap.put(project, configMap); + } + } + return properties.getProperty(ProjectProperties.PROPERTY_TARGET); } + + /** + * Returns the hash string uniquely identifying the target of a project. + * <p/> + * This methods reads the content of the <code>default.properties</code> file present in + * the root folder of the project. + * <p/>The string is equivalent to the return of {@link IAndroidTarget#hashString()}. + * @param project The project for which to return the target hash string. + * @return the hash string or null if the project does not have a target set. + */ + public static String getProjectTargetHashString(IProject project) { + return loadProjectProperties(project, null /*storeConfigs*/); + } /** - * Sets a target hash string in a project's persistent preferences/property storage. + * Sets a target hash string in given project's <code>default.properties</code> file. * @param project The project in which to save the hash string. * @param targetHashString The target hash string to save. This must be the result from * {@link IAndroidTarget#hashString()}. @@ -249,12 +297,82 @@ public class Sdk { * Return the {@link AndroidTargetData} for a given {@link IAndroidTarget}. */ public AndroidTargetData getTargetData(IAndroidTarget target) { - synchronized (mTargetMap) { - return mTargetMap.get(target); + synchronized (mTargetDataMap) { + return mTargetDataMap.get(target); } } /** + * Returns the configuration map for a given project. + * <p/>The Map key are name to be used in the apk filename, while the values are comma separated + * config values. The config value can be passed directly to aapt through the -c option. + */ + public Map<String, String> getProjectConfigs(IProject project) { + return mProjectConfigMap.get(project); + } + + public void setProjectConfigs(IProject project, Map<String, String> configMap) + throws CoreException { + // first set the new map + mProjectConfigMap.put(project, configMap); + + // Now we write this in default.properties. + // Because we don't want to erase other properties from default.properties, we first load + // them + ProjectProperties properties = ProjectProperties.load(project.getLocation().toOSString(), + PropertyType.DEFAULT); + if (properties == null) { + // doesn't exist yet? we create it. + properties = ProjectProperties.create(project.getLocation().toOSString(), + PropertyType.DEFAULT); + } + + // load the current configs, in order to remove the value properties for each of them + // in case a config was removed. + + // get the list of configs. + String configList = properties.getProperty(ProjectProperties.PROPERTY_CONFIGS); + + // this is a comma separated list + String[] configs = configList.split(","); //$NON-NLS-1$ + + boolean hasRemovedConfig = false; + + for (String config : configs) { + if (configMap.containsKey(config) == false) { + hasRemovedConfig = true; + properties.removeProperty(config); + } + } + + // now add the properties. + Set<Entry<String, String>> entrySet = configMap.entrySet(); + StringBuilder sb = new StringBuilder(); + for (Entry<String, String> entry : entrySet) { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(entry.getKey()); + properties.setProperty(entry.getKey(), entry.getValue()); + } + properties.setProperty(ProjectProperties.PROPERTY_CONFIGS, sb.toString()); + + // and rewrite the file. + try { + properties.save(); + } catch (IOException e) { + AdtPlugin.log(e, "Failed to save default.properties for project '%s'", + project.getName()); + } + + // we're done, force a rebuild. If there was removed config, we clean instead of build + // (to remove the obsolete ap_ and apk file from removed configs). + project.build(hasRemovedConfig ? + IncrementalProjectBuilder.CLEAN_BUILD : IncrementalProjectBuilder.FULL_BUILD, + null); + } + + /** * Returns the {@link AvdManager}. If the AvdManager failed to parse the AVD folder, this could * be <code>null</code>. */ @@ -266,14 +384,25 @@ public class Sdk { mManager = manager; mAvdManager = avdManager; + // listen to projects closing + ResourceMonitor monitor = ResourceMonitor.getMonitor(); + monitor.addProjectListener(this); + // pre-compute some paths mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() + SdkConstants.OS_SDK_DOCS_FOLDER); } + + /** + * Cleans and unloads the SDK. + */ + private void dispose() { + ResourceMonitor.getMonitor().removeProjectListener(this); + } void setTargetData(IAndroidTarget target, AndroidTargetData data) { - synchronized (mTargetMap) { - mTargetMap.put(target, data); + synchronized (mTargetDataMap) { + mTargetDataMap.put(target, data); } } @@ -314,6 +443,24 @@ public class Sdk { return null; } + public void projectClosed(IProject project) { + mProjectTargetMap.remove(project); + mProjectConfigMap.remove(project); + } + + public void projectDeleted(IProject project) { + projectClosed(project); + } + + public void projectOpened(IProject project) { + // ignore this. The project will be added to the map the first time the target needs + // to be resolved. + } + + public void projectOpenedWithWorkspace(IProject project) { + // ignore this. The project will be added to the map the first time the target needs + // to be resolved. + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java index 65817c3..b1c57a6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java @@ -19,6 +19,7 @@ package com.android.ide.eclipse.common; import com.android.sdklib.SdkConstants; import java.io.File; +import java.util.regex.Pattern; /** * Constant definition class.<br> @@ -49,17 +50,6 @@ public class AndroidConstants { /** Nature of android projects */ public final static String NATURE = "com.android.ide.eclipse.adt.AndroidNature"; //$NON-NLS-1$ - public final static int PLATFORM_UNKNOWN = 0; - public final static int PLATFORM_LINUX = 1; - public final static int PLATFORM_WINDOWS = 2; - public final static int PLATFORM_DARWIN = 3; - - /** - * Returns current platform, one of {@link #PLATFORM_WINDOWS}, {@link #PLATFORM_DARWIN}, - * {@link #PLATFORM_LINUX} or {@link #PLATFORM_UNKNOWN}. - */ - public final static int CURRENT_PLATFORM = currentPlatform(); - /** Separator for workspace path, i.e. "/". */ public final static String WS_SEP = "/"; //$NON-NLS-1$ /** Separator character for workspace path, i.e. '/'. */ @@ -99,8 +89,6 @@ public class AndroidConstants { public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$ public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$ - /** dex.jar file */ - public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$ /** Name of the android sources directory */ public static final String FD_ANDROID_SOURCES = "sources"; //$NON-NLS-1$ @@ -114,20 +102,21 @@ public class AndroidConstants { public final static String FN_CLASSES_DEX = "classes.dex"; //$NON-NLS-1$ /** Temporary packaged resources file name, i.e. "resources.ap_" */ public final static String FN_RESOURCES_AP_ = "resources.ap_"; //$NON-NLS-1$ + /** Temporary packaged resources file name for a specific set of configuration */ + public final static String FN_RESOURCES_S_AP_ = "resources-%s.ap_"; //$NON-NLS-1$ + public final static Pattern PATTERN_RESOURCES_S_AP_ = + Pattern.compile("resources-.*\\.ap_", Pattern.CASE_INSENSITIVE); - public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? + public final static String FN_ADB = + (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) ? "adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$ - public final static String FN_AAPT = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "aapt.exe" : "aapt"; //$NON-NLS-1$ //$NON-NLS-2$ - - public final static String FN_AIDL = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? - "aidl.exe" : "aidl"; //$NON-NLS-1$ //$NON-NLS-2$ - - public final static String FN_EMULATOR = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? + public final static String FN_EMULATOR = + (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) ? "emulator.exe" : "emulator"; //$NON-NLS-1$ //$NON-NLS-2$ - public final static String FN_TRACEVIEW = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ? + public final static String FN_TRACEVIEW = + (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) ? "traceview.exe" : "traceview"; //$NON-NLS-1$ //$NON-NLS-2$ /** Absolute path of the workspace root, i.e. "/" */ @@ -147,11 +136,6 @@ public class AndroidConstants { * FIXME: remove once the NPW is fixed. */ public final static String OS_SDK_SAMPLES_FOLDER = SdkConstants.FD_SAMPLES + File.separator; - /** Path of the dx.jar file relative to the sdk folder. */ - public final static String OS_SDK_LIBS_DX_JAR = - SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + FN_DX_JAR; - - /** Regexp for single dot */ public final static String RE_DOT = "\\."; //$NON-NLS-1$ /** Regexp for java extension, i.e. "\.java$" */ public final static String RE_JAVA_EXT = "\\.java$"; //$NON-NLS-1$ @@ -229,22 +213,4 @@ public class AndroidConstants { /** The base URL where to find the Android class & manifest documentation */ public static final String CODESITE_BASE_URL = "http://code.google.com/android"; //$NON-NLS-1$ - /** - * Returns current platform - * - * @return one of {@link #PLATFORM_WINDOWS}, {@link #PLATFORM_DARWIN}, - * {@link #PLATFORM_LINUX} or {@link #PLATFORM_UNKNOWN}. - */ - private static int currentPlatform() { - String os = System.getProperty("os.name"); //$NON-NLS-1$ - if (os.startsWith("Mac OS")) { //$NON-NLS-1$ - return PLATFORM_DARWIN; - } else if (os.startsWith("Windows")) { //$NON-NLS-1$ - return PLATFORM_WINDOWS; - } else if (os.startsWith("Linux")) { //$NON-NLS-1$ - return PLATFORM_LINUX; - } - - return PLATFORM_UNKNOWN; - } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java index e3de3af..2c24772 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/IconFactory.java @@ -18,7 +18,7 @@ package com.android.ide.eclipse.editors; import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.common.AndroidConstants; +import com.android.sdklib.SdkConstants; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; @@ -231,7 +231,7 @@ public class IconFactory { // Text measurement varies so slightly depending on the platform int ofx = 0; int ofy = 0; - if (AndroidConstants.CURRENT_PLATFORM == AndroidConstants.PLATFORM_WINDOWS) { + if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) { ofx = +1; ofy = -1; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java index 845db32..d1d8891 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/explorer/ResourceExplorerView.java @@ -160,6 +160,13 @@ public class ResourceExplorerView extends ViewPart implements ISelectionListener // set up the resource manager to send us resource change notification AdtPlugin.getDefault().getResourceMonitor().addResourceEventListener(this); } + + @Override + public void dispose() { + AdtPlugin.getDefault().getResourceMonitor().removeResourceEventListener(this); + + super.dispose(); + } @Override public void setFocus() { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java index dc0f505..59a72fb 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/ResourceMonitor.java @@ -189,20 +189,15 @@ public class ResourceMonitor implements IResourceChangeListener { // the project is opening or closing. IProject project = (IProject)r; - // the OPEN flag represent a toggle in the open/close state of the - // project, but this is sent before the project actually toggles - // its state. - // This means that if the project is closing, isOpen() will return true. - boolean isClosing = project.isOpen(); - if (isClosing) { + if (project.isOpen()) { // notify the listeners. for (IProjectListener pl : mProjectListeners) { - pl.projectClosed(project); + pl.projectOpened(project); } } else { // notify the listeners. for (IProjectListener pl : mProjectListeners) { - pl.projectOpened(project); + pl.projectClosed(project); } } } @@ -287,6 +282,20 @@ public class ResourceMonitor implements IResourceChangeListener { } /** + * Removes an existing folder listener. + * @param listener the listener to remove. + */ + public synchronized void removeFolderListener(IFolderListener listener) { + for (int i = 0 ; i < mFolderListeners.size() ; i++) { + FolderListenerBundle bundle = mFolderListeners.get(i); + if (bundle.listener == listener) { + mFolderListeners.remove(i); + return; + } + } + } + + /** * Adds a project listener. * @param listener The listener to receive the events. */ @@ -305,11 +314,31 @@ public class ResourceMonitor implements IResourceChangeListener { } } + /** + * Removes an existing project listener. + * @param listener the listener to remove. + */ + public synchronized void removeProjectListener(IProjectListener listener) { + mProjectListeners.remove(listener); + } + + /** + * Adds a resource event listener. + * @param listener The listener to receive the events. + */ public synchronized void addResourceEventListener(IResourceEventListener listener) { mEventListeners.add(listener); } /** + * Removes an existing Resource Event listener. + * @param listener the listener to remove. + */ + public synchronized void removeResourceEventListener(IResourceEventListener listener) { + mEventListeners.remove(listener); + } + + /** * Processes the workspace resource change events. */ public void resourceChanged(IResourceChangeEvent event) { diff --git a/eclipse/scripts/collect_sources_for_sdk.sh b/eclipse/scripts/collect_sources_for_sdk.sh new file mode 100644 index 0000000..4637595 --- /dev/null +++ b/eclipse/scripts/collect_sources_for_sdk.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +function usage() { + cat <<EOF + Description: + This script collects all framework Java sources from the current android + source code and places them in a source folder suitable for the eclipse ADT + plugin. + + Usage: + $0 [-n] <android-git-repo root> <sdk/platforms/xyz/sources> + + The source and destination directories must already exist. + Use -n for a dry-run. + +EOF +} + +DRY="" +if [ "-n" == "$1" ]; then + DRY="echo" + shift +fi + +SRC="$1" +DST="$2" + +if [ -z "$SRC" ] || [ -z "$DST" ] || [ ! -d "$SRC" ] || [ ! -d "$DST" ]; then + usage + exit 1 +fi + +function process() { + echo "Examine" $1 +} + +N=0 +E=0 +for i in `find -L "${SRC}/frameworks" -name "*.java"`; do + if [ -f "$i" ]; then + # look for ^package (android.view.blah);$ + PACKAGE=`sed -n '/^package [^ ;]\+; */{s/[^ ]* *\([^ ;]*\).*/\1/p;q}' "$i"` + if [ -n "$PACKAGE" ]; then + PACKAGE=${PACKAGE//./\/} # e.g. android.view => android/view + JAVA=`basename "$i"` # e.g. View.java + [ -z $DRY ] && [ ! -d "$DST/$PACKAGE" ] && mkdir -p -v "$DST/$PACKAGE" + $DRY cp -v "$i" "$DST/$PACKAGE/$JAVA" + N=$((N+1)) + else + echo "Warning: $i does not have a Java package." + E=$((E+1)) + fi + fi +done + +echo "$N java files copied" +[ $E -gt 0 ] && echo "$E warnings" + |
