aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-13 13:04:19 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-13 13:04:19 -0700
commit763ca7d5803d8088e192f4d226ff9e96820c7ace (patch)
tree0826a498b31dc1490e33d660350e81b56b8bc0a1
parent45aacc49a96e083eb68cda88ed0f7e262b7254d1 (diff)
downloadsdk-763ca7d5803d8088e192f4d226ff9e96820c7ace.zip
sdk-763ca7d5803d8088e192f4d226ff9e96820c7ace.tar.gz
sdk-763ca7d5803d8088e192f4d226ff9e96820c7ace.tar.bz2
auto import from //branches/cupcake_rel/...@138607
-rw-r--r--eclipse/changes.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ApkBuilder.java39
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AMReceiver.java160
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ActivityLaunchAction.java97
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchConfiguration.java133
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java655
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java226
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmptyLaunchAction.java38
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/IAndroidLaunchAction.java42
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ILaunchController.java40
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/internal/AndroidClasspathContainerInitializer.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/AbstractGraphicalLayoutEditor.java106
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java44
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java31
-rw-r--r--scripts/android_rules.xml15
26 files changed, 1135 insertions, 577 deletions
diff --git a/eclipse/changes.txt b/eclipse/changes.txt
index 781930c..8cd843e 100644
--- a/eclipse/changes.txt
+++ b/eclipse/changes.txt
@@ -1,4 +1,5 @@
0.9.0 (work in progress)
+- Projects now store generated Java files (R.java/Manifest.java and output from aidl) in a 'gen' source folder.
- Support for the new Android SDK with support for multiple versions of the Android platform and for vendor supplied add-ons.
* New Project Wizard lets you choose which platform/add-on to target.
* Project properties (right click project in Package Explorer, then "Properties"), lets you edit project target.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index f86f5b2..39e6dd5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -481,6 +481,12 @@
style="push"
toolbarPath="android_project"
tooltip="Opens a wizard to help create a new Android XML file">
+ <enablement>
+ <objectState
+ name="projectNature"
+ value="com.android.ide.eclipse.adt.AndroidNature">
+ </objectState>
+ </enablement>
</action>
<action
class="com.android.ide.eclipse.adt.wizards.actions.NewProjectAction"
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 18d9745..f8a969e 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
@@ -966,9 +966,10 @@ public class ApkBuilder extends BaseBuilder {
* @param javaProject the javaProject object.
* @param referencedJavaProjects the java projects that this project references.
* @throws IOException
+ * @throws CoreException
*/
private void writeStandardResources(SignedJarBuilder jarBuilder, IJavaProject javaProject,
- IJavaProject[] referencedJavaProjects) throws IOException {
+ IJavaProject[] referencedJavaProjects) throws IOException, CoreException {
IWorkspace ws = ResourcesPlugin.getWorkspace();
IWorkspaceRoot wsRoot = ws.getRoot();
@@ -978,7 +979,9 @@ public class ApkBuilder extends BaseBuilder {
writeStandardProjectResources(jarBuilder, javaProject, wsRoot, list);
for (IJavaProject referencedJavaProject : referencedJavaProjects) {
- writeStandardProjectResources(jarBuilder, referencedJavaProject, wsRoot, list);
+ if (referencedJavaProject.getProject().hasNature(AndroidConstants.NATURE)) {
+ writeStandardProjectResources(jarBuilder, referencedJavaProject, wsRoot, list);
+ }
}
}
@@ -1067,7 +1070,9 @@ public class ApkBuilder extends BaseBuilder {
}
/**
- * Returns the list of the output folders for the specified {@link IJavaProject} objects.
+ * Returns the list of the output folders for the specified {@link IJavaProject} objects, if
+ * they are Android projects.
+ *
* @param referencedJavaProjects the java projects.
* @return an array, always. Can be empty.
* @throws CoreException
@@ -1079,19 +1084,21 @@ public class ApkBuilder extends BaseBuilder {
IWorkspaceRoot wsRoot = ws.getRoot();
for (IJavaProject javaProject : referencedJavaProjects) {
- // get the output folder
- IPath path = null;
- try {
- path = javaProject.getOutputLocation();
- } catch (JavaModelException e) {
- continue;
- }
-
- IResource outputResource = wsRoot.findMember(path);
- if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
- String outputOsPath = outputResource.getLocation().toOSString();
-
- list.add(outputOsPath);
+ if (javaProject.getProject().hasNature(AndroidConstants.NATURE)) {
+ // get the output folder
+ IPath path = null;
+ try {
+ path = javaProject.getOutputLocation();
+ } catch (JavaModelException e) {
+ continue;
+ }
+
+ IResource outputResource = wsRoot.findMember(path);
+ if (outputResource != null && outputResource.getType() == IResource.FOLDER) {
+ String outputOsPath = outputResource.getLocation().toOSString();
+
+ list.add(outputOsPath);
+ }
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AMReceiver.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AMReceiver.java
new file mode 100644
index 0000000..8fdcdf9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AMReceiver.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ide.eclipse.adt.AdtPlugin;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Output receiver for am process (Activity Manager)
+ *
+ * Monitors adb output for am errors, and retries launch as appropriate.
+ */
+public class AMReceiver extends MultiLineReceiver {
+
+ private static final int MAX_ATTEMPT_COUNT = 5;
+ private static final Pattern sAmErrorType = Pattern.compile("Error type (\\d+)"); //$NON-NLS-1$
+
+ private final DelayedLaunchInfo mLaunchInfo;
+ private final IDevice mDevice;
+ private final ILaunchController mLaunchController;
+
+ /**
+ * Basic constructor.
+ *
+ * @param launchInfo the {@link DelayedLaunchInfo} associated with the am process.
+ * @param device the Android device on which the launch is done.
+ * @param launchController the {@link ILaunchController} that is managing the launch
+ */
+ public AMReceiver(DelayedLaunchInfo launchInfo, IDevice device,
+ ILaunchController launchController) {
+ mLaunchInfo = launchInfo;
+ mDevice = device;
+ mLaunchController = launchController;
+ }
+
+ /**
+ * Monitors the am process for error messages. If an error occurs, will reattempt launch up to
+ * <code>MAX_ATTEMPT_COUNT</code> times.
+ *
+ * @param lines a portion of the am output
+ *
+ * @see MultiLineReceiver#processNewLines(String[])
+ */
+ @Override
+ public void processNewLines(String[] lines) {
+ // first we check if one starts with error
+ ArrayList<String> array = new ArrayList<String>();
+ boolean error = false;
+ boolean warning = false;
+ for (String s : lines) {
+ // ignore empty lines.
+ if (s.length() == 0) {
+ continue;
+ }
+
+ // check for errors that output an error type, if the attempt count is still
+ // valid. If not the whole text will be output in the console
+ if (mLaunchInfo.getAttemptCount() < MAX_ATTEMPT_COUNT &&
+ mLaunchInfo.isCancelled() == false) {
+ Matcher m = sAmErrorType.matcher(s);
+ if (m.matches()) {
+ // get the error type
+ int type = Integer.parseInt(m.group(1));
+
+ final int waitTime = 3;
+ String msg;
+
+ switch (type) {
+ case 1:
+ /* Intended fall through */
+ case 2:
+ msg = String.format(
+ "Device not ready. Waiting %1$d seconds before next attempt.",
+ waitTime);
+ break;
+ case 3:
+ msg = String.format(
+ "New package not yet registered with the system. Waiting %1$d seconds before next attempt.",
+ waitTime);
+ break;
+ default:
+ msg = String.format(
+ "Device not ready (%2$d). Waiting %1$d seconds before next attempt.",
+ waitTime, type);
+ break;
+
+ }
+
+ AdtPlugin.printToConsole(mLaunchInfo.getProject(), msg);
+
+ // launch another thread, that waits a bit and attempts another launch
+ new Thread("Delayed Launch attempt") {
+ @Override
+ public void run() {
+ try {
+ sleep(waitTime * 1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ mLaunchController.launchApp(mLaunchInfo, mDevice);
+ }
+ }.start();
+
+ // no need to parse the rest
+ return;
+ }
+ }
+
+ // check for error if needed
+ if (error == false && s.startsWith("Error:")) { //$NON-NLS-1$
+ error = true;
+ }
+ if (warning == false && s.startsWith("Warning:")) { //$NON-NLS-1$
+ warning = true;
+ }
+
+ // add the line to the list
+ array.add("ActivityManager: " + s); //$NON-NLS-1$
+ }
+
+ // then we display them in the console
+ if (warning || error) {
+ AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), array.toArray());
+ } else {
+ AdtPlugin.printToConsole(mLaunchInfo.getProject(), array.toArray());
+ }
+
+ // if error then we cancel the launch, and remove the delayed info
+ if (error) {
+ mLaunchController.stopLaunch(mLaunchInfo);
+ }
+ }
+
+ /**
+ * Returns true if launch has been cancelled
+ */
+ public boolean isCancelled() {
+ return mLaunchInfo.isCancelled();
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ActivityLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ActivityLaunchAction.java
new file mode 100644
index 0000000..1aa5a9a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ActivityLaunchAction.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ddmlib.IDevice;
+import com.android.ide.eclipse.adt.AdtPlugin;
+
+import java.io.IOException;
+
+/**
+ * Launches the given activity
+ */
+public class ActivityLaunchAction implements IAndroidLaunchAction {
+
+ private final String mActivity;
+ private final ILaunchController mLaunchController;
+
+ /**
+ * Creates a ActivityLaunchAction
+ *
+ * @param activity fully qualified activity name to launch
+ * @param controller the {@link ILaunchController} that performs launch
+ */
+ public ActivityLaunchAction(String activity, ILaunchController controller) {
+ mActivity = activity;
+ mLaunchController = controller;
+ }
+
+ /**
+ * Launches the activity on targeted device
+ *
+ * @param info the {@link DelayedLaunchInfo} that contains launch details
+ * @param device the Android device to perform action on
+ *
+ * @see IAndroidLaunchAction#doLaunchAction(DelayedLaunchInfo, IDevice)
+ */
+ public boolean doLaunchAction(DelayedLaunchInfo info, IDevice device) {
+ try {
+ String msg = String.format("Starting activity %1$s on device ", mActivity,
+ device);
+ AdtPlugin.printToConsole(info.getProject(), msg);
+
+ // In debug mode, we need to add the info to the list of application monitoring
+ // client changes.
+ // increment launch attempt count, to handle retries and timeouts
+ info.incrementAttemptCount();
+
+ // now we actually launch the app.
+ device.executeShellCommand("am start" //$NON-NLS-1$
+ + (info.isDebugMode() ? " -D" //$NON-NLS-1$
+ : "") //$NON-NLS-1$
+ + " -n " //$NON-NLS-1$
+ + info.getPackageName() + "/" //$NON-NLS-1$
+ + mActivity.replaceAll("\\$", "\\\\\\$"), //$NON-NLS-1$ //$NON-NLS-2$
+ new AMReceiver(info, device, mLaunchController));
+
+ // if the app is not a debug app, we need to do some clean up, as
+ // the process is done!
+ if (info.isDebugMode() == false) {
+ // stop the launch object, since there's no debug, and it can't
+ // provide any control over the app
+ return false;
+ }
+ } catch (IOException e) {
+ // something went wrong trying to launch the app.
+ // lets stop the Launch
+ AdtPlugin.printErrorToConsole(info.getProject(),
+ String.format("Launch error: %s", e.getMessage()));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a description of the activity being launched
+ *
+ * @see IAndroidLaunchAction#getLaunchDescription()
+ */
+ public String getLaunchDescription() {
+ return String.format("%1$s activity launch", mActivity);
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
index 7029206..42927c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
@@ -26,7 +26,7 @@ import org.eclipse.debug.core.model.ISourceLocator;
* Custom implementation of Launch to allow access to the LaunchManager
*
*/
-class AndroidLaunch extends Launch {
+public class AndroidLaunch extends Launch {
/**
* Basic constructor does nothing special
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchConfiguration.java
new file mode 100644
index 0000000..448cda6
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchConfiguration.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+/**
+ * Launch configuration data. This stores the result of querying the
+ * {@link ILaunchConfiguration} so that it's only done once.
+ */
+public class AndroidLaunchConfiguration {
+
+ /**
+ * Launch action. See {@link LaunchConfigDelegate#ACTION_DEFAULT},
+ * {@link LaunchConfigDelegate#ACTION_ACTIVITY},
+ * {@link LaunchConfigDelegate#ACTION_DO_NOTHING}
+ */
+ public int mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION;
+
+ public static final boolean AUTO_TARGET_MODE = true;
+
+ /**
+ * Target selection mode.
+ * <ul>
+ * <li><code>true</code>: automatic mode, see {@link #AUTO_TARGET_MODE}</li>
+ * <li><code>false</code>: manual mode</li>
+ * </ul>
+ */
+ public boolean mTargetMode = LaunchConfigDelegate.DEFAULT_TARGET_MODE;
+
+ /**
+ * Indicates whether the emulator should be called with -wipe-data
+ */
+ public boolean mWipeData = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
+
+ /**
+ * Indicates whether the emulator should be called with -no-boot-anim
+ */
+ public boolean mNoBootAnim = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM;
+
+ /**
+ * AVD Name.
+ */
+ public String mAvdName = null;
+
+ public String mNetworkSpeed = EmulatorConfigTab.getSpeed(
+ LaunchConfigDelegate.DEFAULT_SPEED);
+ public String mNetworkDelay = EmulatorConfigTab.getDelay(
+ LaunchConfigDelegate.DEFAULT_DELAY);
+
+ /**
+ * Optional custom command line parameter to launch the emulator
+ */
+ public String mEmulatorCommandLine;
+
+ /**
+ * Initialized the structure from an ILaunchConfiguration object.
+ * @param config
+ */
+ public void set(ILaunchConfiguration config) {
+ try {
+ mLaunchAction = config.getAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION,
+ mLaunchAction);
+ } catch (CoreException e1) {
+ // nothing to be done here, we'll use the default value
+ }
+
+ try {
+ mTargetMode = config.getAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
+ mTargetMode);
+ } catch (CoreException e) {
+ // nothing to be done here, we'll use the default value
+ }
+
+ try {
+ mAvdName = config.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, mAvdName);
+ } catch (CoreException e) {
+ // ignore
+ }
+
+ int index = LaunchConfigDelegate.DEFAULT_SPEED;
+ try {
+ index = config.getAttribute(LaunchConfigDelegate.ATTR_SPEED, index);
+ } catch (CoreException e) {
+ // nothing to be done here, we'll use the default value
+ }
+ mNetworkSpeed = EmulatorConfigTab.getSpeed(index);
+
+ index = LaunchConfigDelegate.DEFAULT_DELAY;
+ try {
+ index = config.getAttribute(LaunchConfigDelegate.ATTR_DELAY, index);
+ } catch (CoreException e) {
+ // nothing to be done here, we'll use the default value
+ }
+ mNetworkDelay = EmulatorConfigTab.getDelay(index);
+
+ try {
+ mEmulatorCommandLine = config.getAttribute(
+ LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$
+ } catch (CoreException e) {
+ // lets not do anything here, we'll use the default value
+ }
+
+ try {
+ mWipeData = config.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, mWipeData);
+ } catch (CoreException e) {
+ // nothing to be done here, we'll use the default value
+ }
+
+ try {
+ mNoBootAnim = config.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM,
+ mNoBootAnim);
+ } catch (CoreException e) {
+ // nothing to be done here, we'll use the default value
+ }
+ }
+}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
index 111d6b3..88ee8b6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
@@ -17,17 +17,19 @@
package com.android.ide.eclipse.adt.launch;
import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
+import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
+import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.ddmlib.Client;
import com.android.ddmlib.ClientData;
import com.android.ddmlib.Device;
+import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.MultiLineReceiver;
import com.android.ddmlib.SyncService;
-import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
-import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
-import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.ddmlib.SyncService.SyncResult;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.launch.DelayedLaunchInfo.InstallRetryMode;
import com.android.ide.eclipse.adt.launch.DeviceChooserDialog.DeviceChooserResponse;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.adt.sdk.Sdk;
@@ -72,7 +74,7 @@ import java.util.regex.Pattern;
* it.
*/
public final class AndroidLaunchController implements IDebugBridgeChangeListener,
- IDeviceChangeListener, IClientChangeListener {
+ IDeviceChangeListener, IClientChangeListener, ILaunchController {
private static final String FLAG_AVD = "-avd"; //$NON-NLS-1$
private static final String FLAG_NETDELAY = "-netdelay"; //$NON-NLS-1$
@@ -80,83 +82,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
private static final String FLAG_WIPE_DATA = "-wipe-data"; //$NON-NLS-1$
private static final String FLAG_NO_BOOT_ANIM = "-no-boot-anim"; //$NON-NLS-1$
- private static final int MAX_ATTEMPT_COUNT = 5;
-
- private final static Pattern sAmErrorType = Pattern.compile("Error type (\\d+)"); //$NON-NLS-1$
-
- /**
- * A delayed launch waiting for a device to be present or ready before the
- * application is launched.
- */
- static final class DelayedLaunchInfo {
- /** The device on which to launch the app */
- Device mDevice = null;
-
- /** The eclipse project */
- IProject mProject;
-
- /** Package name */
- String mPackageName;
-
- /** fully qualified name of the activity */
- String mActivity;
-
- /** IFile to the package (.apk) file */
- IFile mPackageFile;
-
- /** Debuggable attribute of the manifest file. */
- Boolean mDebuggable = null;
-
- /** Required ApiVersionNumber by the app. 0 means no requirements */
- int mRequiredApiVersionNumber = 0;
-
- InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
-
- /**
- * Launch action. See {@link LaunchConfigDelegate#ACTION_DEFAULT},
- * {@link LaunchConfigDelegate#ACTION_ACTIVITY},
- * {@link LaunchConfigDelegate#ACTION_DO_NOTHING}
- */
- int mLaunchAction;
-
- /** the launch object */
- AndroidLaunch mLaunch;
-
- /** the monitor object */
- IProgressMonitor mMonitor;
-
- /** debug mode flag */
- boolean mDebugMode;
-
- int mAttemptCount = 0;
-
- boolean mCancelled = false;
-
- /** Basic constructor with activity and package info. */
- private DelayedLaunchInfo(IProject project, String packageName, String activity,
- IFile pack, Boolean debuggable, int requiredApiVersionNumber, int launchAction,
- AndroidLaunch launch, IProgressMonitor monitor) {
- mProject = project;
- mPackageName = packageName;
- mActivity = activity;
- mPackageFile = pack;
- mLaunchAction = launchAction;
- mLaunch = launch;
- mMonitor = monitor;
- mDebuggable = debuggable;
- mRequiredApiVersionNumber = requiredApiVersionNumber;
- }
- }
-
/**
* Map to store {@link ILaunchConfiguration} objects that must be launched as simple connection
* to running application. The integer is the port on which to connect.
* <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b>
*/
- private final static HashMap<ILaunchConfiguration, Integer> sRunningAppMap =
+ private static final HashMap<ILaunchConfiguration, Integer> sRunningAppMap =
new HashMap<ILaunchConfiguration, Integer>();
- private final static Object sListLock = sRunningAppMap;
+ private static final Object sListLock = sRunningAppMap;
/**
* List of {@link DelayedLaunchInfo} waiting for an emulator to connect.
@@ -190,243 +124,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/** static instance for singleton */
private static AndroidLaunchController sThis = new AndroidLaunchController();
- enum InstallRetryMode {
- NEVER, ALWAYS, PROMPT;
- }
-
- /**
- * Launch configuration data. This stores the result of querying the
- * {@link ILaunchConfiguration} so that it's only done once.
- */
- static final class AndroidLaunchConfiguration {
-
- /**
- * Launch action. See {@link LaunchConfigDelegate#ACTION_DEFAULT},
- * {@link LaunchConfigDelegate#ACTION_ACTIVITY},
- * {@link LaunchConfigDelegate#ACTION_DO_NOTHING}
- */
- public int mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION;
-
- public static final boolean AUTO_TARGET_MODE = true;
-
- /**
- * Target selection mode.
- * <ul>
- * <li><code>true</code>: automatic mode, see {@link #AUTO_TARGET_MODE}</li>
- * <li><code>false</code>: manual mode</li>
- * </ul>
- */
- public boolean mTargetMode = LaunchConfigDelegate.DEFAULT_TARGET_MODE;
-
- /**
- * Indicates whether the emulator should be called with -wipe-data
- */
- public boolean mWipeData = LaunchConfigDelegate.DEFAULT_WIPE_DATA;
-
- /**
- * Indicates whether the emulator should be called with -no-boot-anim
- */
- public boolean mNoBootAnim = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM;
-
- /**
- * AVD Name.
- */
- public String mAvdName = null;
-
- public String mNetworkSpeed = EmulatorConfigTab.getSpeed(
- LaunchConfigDelegate.DEFAULT_SPEED);
- public String mNetworkDelay = EmulatorConfigTab.getDelay(
- LaunchConfigDelegate.DEFAULT_DELAY);
-
- /**
- * Optional custom command line parameter to launch the emulator
- */
- public String mEmulatorCommandLine;
-
- /**
- * Initialized the structure from an ILaunchConfiguration object.
- * @param config
- */
- public void set(ILaunchConfiguration config) {
- try {
- mLaunchAction = config.getAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION,
- mLaunchAction);
- } catch (CoreException e1) {
- // nothing to be done here, we'll use the default value
- }
-
- try {
- mTargetMode = config.getAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE,
- mTargetMode);
- } catch (CoreException e) {
- // nothing to be done here, we'll use the default value
- }
-
- try {
- mAvdName = config.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, mAvdName);
- } catch (CoreException e) {
- }
-
- int index = LaunchConfigDelegate.DEFAULT_SPEED;
- try {
- index = config.getAttribute(LaunchConfigDelegate.ATTR_SPEED, index);
- } catch (CoreException e) {
- // nothing to be done here, we'll use the default value
- }
- mNetworkSpeed = EmulatorConfigTab.getSpeed(index);
-
- index = LaunchConfigDelegate.DEFAULT_DELAY;
- try {
- index = config.getAttribute(LaunchConfigDelegate.ATTR_DELAY, index);
- } catch (CoreException e) {
- // nothing to be done here, we'll use the default value
- }
- mNetworkDelay = EmulatorConfigTab.getDelay(index);
-
- try {
- mEmulatorCommandLine = config.getAttribute(
- LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$
- } catch (CoreException e) {
- // lets not do anything here, we'll use the default value
- }
-
- try {
- mWipeData = config.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, mWipeData);
- } catch (CoreException e) {
- // nothing to be done here, we'll use the default value
- }
-
- try {
- mNoBootAnim = config.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM,
- mNoBootAnim);
- } catch (CoreException e) {
- // nothing to be done here, we'll use the default value
- }
- }
- }
- /**
- * Output receiver for am process (activity Manager);
- */
- private final class AMReceiver extends MultiLineReceiver {
- private DelayedLaunchInfo mLaunchInfo;
- private Device mDevice;
-
- /**
- * Basic constructor.
- * @param launchInfo The launch info associated with the am process.
- * @param device The device on which the launch is done.
- */
- public AMReceiver(DelayedLaunchInfo launchInfo, Device device) {
- mLaunchInfo = launchInfo;
- mDevice = device;
- }
-
- @Override
- public void processNewLines(String[] lines) {
- // first we check if one starts with error
- ArrayList<String> array = new ArrayList<String>();
- boolean error = false;
- boolean warning = false;
- for (String s : lines) {
- // ignore empty lines.
- if (s.length() == 0) {
- continue;
- }
-
- // check for errors that output an error type, if the attempt count is still
- // valid. If not the whole text will be output in the console
- if (mLaunchInfo.mAttemptCount < MAX_ATTEMPT_COUNT &&
- mLaunchInfo.mCancelled == false) {
- Matcher m = sAmErrorType.matcher(s);
- if (m.matches()) {
- // get the error type
- int type = Integer.parseInt(m.group(1));
-
- final int waitTime = 3;
- String msg;
-
- switch (type) {
- case 1:
- /* Intended fall through */
- case 2:
- msg = String.format(
- "Device not ready. Waiting %1$d seconds before next attempt.",
- waitTime);
- break;
- case 3:
- msg = String.format(
- "New package not yet registered with the system. Waiting %1$d seconds before next attempt.",
- waitTime);
- break;
- default:
- msg = String.format(
- "Device not ready (%2$d). Waiting %1$d seconds before next attempt.",
- waitTime, type);
- break;
-
- }
-
- AdtPlugin.printToConsole(mLaunchInfo.mProject, msg);
-
- // launch another thread, that waits a bit and attempts another launch
- new Thread("Delayed Launch attempt") {
- @Override
- public void run() {
- try {
- sleep(waitTime * 1000);
- } catch (InterruptedException e) {
- }
-
- launchApp(mLaunchInfo, mDevice);
- }
- }.start();
-
- // no need to parse the rest
- return;
- }
- }
-
- // check for error if needed
- if (error == false && s.startsWith("Error:")) { //$NON-NLS-1$
- error = true;
- }
- if (warning == false && s.startsWith("Warning:")) { //$NON-NLS-1$
- warning = true;
- }
-
- // add the line to the list
- array.add("ActivityManager: " + s); //$NON-NLS-1$
- }
-
- // then we display them in the console
- if (warning || error) {
- AdtPlugin.printErrorToConsole(mLaunchInfo.mProject, array.toArray());
- } else {
- AdtPlugin.printToConsole(mLaunchInfo.mProject, array.toArray());
- }
-
- // if error then we cancel the launch, and remove the delayed info
- if (error) {
- mLaunchInfo.mLaunch.stopLaunch();
- synchronized (sListLock) {
- mWaitingForReadyEmulatorList.remove(mLaunchInfo);
- }
- }
- }
-
- public boolean isCancelled() {
- return false;
- }
- }
/**
* Output receiver for "pm install package.apk" command line.
*/
- private final static class InstallReceiver extends MultiLineReceiver {
+ private static final class InstallReceiver extends MultiLineReceiver {
- private final static String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
- private final static Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
+ private static final String SUCCESS_OUTPUT = "Success"; //$NON-NLS-1$
+ private static final Pattern FAILURE_PATTERN = Pattern.compile("Failure\\s+\\[(.*)\\]"); //$NON-NLS-1$
private String mSuccess = null;
@@ -533,7 +239,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
LaunchConfigDelegate.DEFAULT_TARGET_MODE);
// default AVD: None
- wc.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String)null);
+ wc.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String) null);
// set the default network speed
wc.setAttribute(LaunchConfigDelegate.ATTR_SPEED,
@@ -602,30 +308,24 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param apk the resource to the apk to launch.
* @param debuggable the debuggable value of the app, or null if not set.
* @param requiredApiVersionNumber the api version required by the app, or -1 if none.
- * @param activity the class to provide to am to launch
+ * @param launchAction the action to perform after app sync
* @param config the launch configuration
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
- String packageName, Boolean debuggable, int requiredApiVersionNumber, String activity,
- final AndroidLaunchConfiguration config, final AndroidLaunch launch,
- IProgressMonitor monitor) {
+ String packageName, Boolean debuggable, int requiredApiVersionNumber,
+ final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
+ final AndroidLaunch launch, IProgressMonitor monitor) {
- String message;
- if (config.mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING) {
- message = String.format("Only Syncing Application Package");
- } else {
- message = String.format("Launching: %1$s", activity);
- }
+ String message = String.format("Performing %1$s", launchAction.getLaunchDescription());
AdtPlugin.printToConsole(project, message);
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
- activity, apk, debuggable, requiredApiVersionNumber, config.mLaunchAction,
- launch, monitor);
+ launchAction, apk, debuggable, requiredApiVersionNumber, launch, monitor);
// set the debug mode
- launchInfo.mDebugMode = mode.equals(ILaunchManager.DEBUG_MODE);
+ launchInfo.setDebugMode(mode.equals(ILaunchManager.DEBUG_MODE));
// get the SDK
Sdk currentSdk = Sdk.getCurrent();
@@ -657,7 +357,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (config.mTargetMode == AndroidLaunchConfiguration.AUTO_TARGET_MODE) {
// if we are in automatic target mode, we need to find the current devices
- Device[] devices = AndroidDebugBridge.getBridge().getDevices();
+ IDevice[] devices = AndroidDebugBridge.getBridge().getDevices();
// first check if we have a preferred AVD name, and if it actually exists, and is valid
// (ie able to run the project).
@@ -677,7 +377,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (preferredAvd != null) {
// look for a matching device
- for (Device d : devices) {
+ for (IDevice d : devices) {
String deviceAvd = d.getAvdName();
if (deviceAvd != null && deviceAvd.equals(config.mAvdName)) {
response.setDeviceToUse(d);
@@ -704,12 +404,12 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
// no (valid) preferred AVD? look for one.
- HashMap<Device, AvdInfo> compatibleRunningAvds = new HashMap<Device, AvdInfo>();
+ HashMap<IDevice, AvdInfo> compatibleRunningAvds = new HashMap<IDevice, AvdInfo>();
boolean hasDevice = false; // if there's 1+ device running, we may force manual mode,
// as we cannot always detect proper compatibility with
// devices. This is the case if the project target is not
// a standard platform
- for (Device d : devices) {
+ for (IDevice d : devices) {
String deviceAvd = d.getAvdName();
if (deviceAvd != null) { // physical devices return null.
AvdInfo info = avdManager.getAvd(deviceAvd);
@@ -770,11 +470,11 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
AdtPlugin.printErrorToConsole(project, String.format(
"Failed to find a AVD compatible with target '%1$s'. Launch aborted.",
projectTarget.getName()));
- launch.stopLaunch();
+ stopLaunch(launchInfo);
return;
}
} else if (hasDevice == false && compatibleRunningAvds.size() == 1) {
- Entry<Device, AvdInfo> e = compatibleRunningAvds.entrySet().iterator().next();
+ Entry<IDevice, AvdInfo> e = compatibleRunningAvds.entrySet().iterator().next();
response.setDeviceToUse(e.getKey());
// get the AvdInfo, if null, the device is a physical device.
@@ -810,13 +510,13 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// or the AVD to launch.
DeviceChooserDialog dialog = new DeviceChooserDialog(
AdtPlugin.getDisplay().getActiveShell(),
- response, launchInfo.mPackageName, projectTarget);
+ response, launchInfo.getPackageName(), projectTarget);
if (dialog.open() == Dialog.OK) {
AndroidLaunchController.this.continueLaunch(response, project, launch,
launchInfo, config);
} else {
AdtPlugin.printErrorToConsole(project, "Launch canceled!");
- launch.stopLaunch();
+ stopLaunch(launchInfo);
return;
}
} catch (Exception e) {
@@ -830,7 +530,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
AdtPlugin.printErrorToConsole(project,
String.format("Error during launch: %s", msg));
- launch.stopLaunch();
+ stopLaunch(launchInfo);
}
}
});
@@ -871,15 +571,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// stop the launch and return
mWaitingForEmulatorLaunches.remove(launchInfo);
AdtPlugin.printErrorToConsole(project, "Launch canceled!");
- launch.stopLaunch();
+ stopLaunch(launchInfo);
return;
}
return;
}
} else if (response.getDeviceToUse() != null) {
- launchInfo.mDevice = response.getDeviceToUse();
- simpleLaunch(launchInfo, launchInfo.mDevice);
+ launchInfo.setDevice(response.getDeviceToUse());
+ simpleLaunch(launchInfo, launchInfo.getDevice());
}
}
}.start();
@@ -932,12 +632,12 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* "release" mode instead of "debug"</li>
* <ul>
*/
- private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, Device device) {
+ private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, IDevice device) {
if (device != null) {
// check the app required API level versus the target device API level
- String deviceApiVersionName = device.getProperty(Device.PROP_BUILD_VERSION);
- String value = device.getProperty(Device.PROP_BUILD_VERSION_NUMBER);
+ String deviceApiVersionName = device.getProperty(IDevice.PROP_BUILD_VERSION);
+ String value = device.getProperty(IDevice.PROP_BUILD_VERSION_NUMBER);
int deviceApiVersionNumber = 0;
try {
deviceApiVersionNumber = Integer.parseInt(value);
@@ -945,30 +645,30 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// pass, we'll keep the deviceVersionNumber value at 0.
}
- if (launchInfo.mRequiredApiVersionNumber == 0) {
+ if (launchInfo.getRequiredApiVersionNumber() == 0) {
// warn the API level requirement is not set.
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Application does not specify an API level requirement!");
// and display the target device API level (if known)
if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"WARNING: Unknown device API version!");
} else {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
"Device API version is %1$d (Android %2$s)", deviceApiVersionNumber,
deviceApiVersionName));
}
} else { // app requires a specific API level
if (deviceApiVersionName == null || deviceApiVersionNumber == 0) {
- AdtPlugin.printToConsole(launchInfo.mProject,
+ AdtPlugin.printToConsole(launchInfo.getProject(),
"WARNING: Unknown device API version!");
- } else if (deviceApiVersionNumber < launchInfo.mRequiredApiVersionNumber) {
+ } else if (deviceApiVersionNumber < launchInfo.getRequiredApiVersionNumber()) {
String msg = String.format(
"ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).",
- launchInfo.mRequiredApiVersionNumber, deviceApiVersionNumber,
+ launchInfo.getRequiredApiVersionNumber(), deviceApiVersionNumber,
deviceApiVersionName);
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
// abort the launch
return false;
@@ -976,33 +676,33 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
// now checks that the device/app can be debugged (if needed)
- if (device.isEmulator() == false && launchInfo.mDebugMode) {
- String debuggableDevice = device.getProperty(Device.PROP_DEBUGGABLE);
+ if (device.isEmulator() == false && launchInfo.isDebugMode()) {
+ String debuggableDevice = device.getProperty(IDevice.PROP_DEBUGGABLE);
if (debuggableDevice != null && debuggableDevice.equals("0")) { //$NON-NLS-1$
// the device is "secure" and requires apps to declare themselves as debuggable!
- if (launchInfo.mDebuggable == null) {
+ if (launchInfo.getDebuggable() == null) {
String message1 = String.format(
"Device '%1$s' requires that applications explicitely declare themselves as debuggable in their manifest.",
device.getSerialNumber());
String message2 = String.format("Application '%1$s' does not have the attribute 'debuggable' set to TRUE in its manifest and cannot be debugged.",
- launchInfo.mPackageName);
- AdtPlugin.printErrorToConsole(launchInfo.mProject, message1, message2);
+ launchInfo.getPackageName());
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), message1, message2);
// because am -D does not check for ro.debuggable and the
// 'debuggable' attribute, it is important we do not use the -D option
// in this case or the app will wait for a debugger forever and never
// really launch.
- launchInfo.mDebugMode = false;
- } else if (launchInfo.mDebuggable == Boolean.FALSE) {
+ launchInfo.setDebugMode(false);
+ } else if (launchInfo.getDebuggable() == Boolean.FALSE) {
String message = String.format("Application '%1$s' has its 'debuggable' attribute set to FALSE and cannot be debugged.",
- launchInfo.mPackageName);
- AdtPlugin.printErrorToConsole(launchInfo.mProject, message);
+ launchInfo.getPackageName());
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), message);
// because am -D does not check for ro.debuggable and the
// 'debuggable' attribute, it is important we do not use the -D option
// in this case or the app will wait for a debugger forever and never
// really launch.
- launchInfo.mDebugMode = false;
+ launchInfo.setDebugMode(false);
}
}
}
@@ -1019,18 +719,18 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param device
* @return true if succeed
*/
- private boolean simpleLaunch(DelayedLaunchInfo launchInfo, Device device) {
+ private boolean simpleLaunch(DelayedLaunchInfo launchInfo, IDevice device) {
// API level check
if (checkBuildInfo(launchInfo, device) == false) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
- launchInfo.mLaunch.stopLaunch();
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), "Launch canceled!");
+ stopLaunch(launchInfo);
return false;
}
// sync the app
if (syncApp(launchInfo, device) == false) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, "Launch canceled!");
- launchInfo.mLaunch.stopLaunch();
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), "Launch canceled!");
+ stopLaunch(launchInfo);
return false;
}
@@ -1048,16 +748,16 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param device the device on which to sync the application
* @return true if the install succeeded.
*/
- private boolean syncApp(DelayedLaunchInfo launchInfo, Device device) {
+ private boolean syncApp(DelayedLaunchInfo launchInfo, IDevice device) {
SyncService sync = device.getSyncService();
if (sync != null) {
- IPath path = launchInfo.mPackageFile.getLocation();
+ IPath path = launchInfo.getPackageFile().getLocation();
String message = String.format("Uploading %1$s onto device '%2$s'",
path.lastSegment(), device.getSerialNumber());
- AdtPlugin.printToConsole(launchInfo.mProject, message);
+ AdtPlugin.printToConsole(launchInfo.getProject(), message);
String osLocalPath = path.toOSString();
- String apkName = launchInfo.mPackageFile.getName();
+ String apkName = launchInfo.getPackageFile().getName();
String remotePath = "/data/local/tmp/" + apkName; //$NON-NLS-1$
SyncResult result = sync.pushFile(osLocalPath, remotePath,
@@ -1066,7 +766,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (result.getCode() != SyncService.RESULT_OK) {
String msg = String.format("Failed to upload %1$s on '%2$s': %3$s",
apkName, device.getSerialNumber(), result.getMessage());
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
return false;
}
@@ -1087,7 +787,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
});
} catch (IOException e) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, String.format(
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format(
"Failed to delete temporary package: %1$s", e.getMessage()));
return false;
}
@@ -1097,8 +797,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
String msg = String.format(
"Failed to upload %1$s on device '%2$s': Unable to open sync connection!",
- launchInfo.mPackageFile.getName(), device.getSerialNumber());
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+ launchInfo.getPackageFile().getName(), device.getSerialNumber());
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
return false;
}
@@ -1110,10 +810,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param device The device on which the launch is done.
*/
private boolean installPackage(DelayedLaunchInfo launchInfo, final String remotePath,
- final Device device) {
+ final IDevice device) {
- String message = String.format("Installing %1$s...", launchInfo.mPackageFile.getName());
- AdtPlugin.printToConsole(launchInfo.mProject, message);
+ String message = String.format("Installing %1$s...", launchInfo.getPackageFile().getName());
+ AdtPlugin.printToConsole(launchInfo.getProject(), message);
try {
String result = doInstall(launchInfo, remotePath, device, false /* reinstall */);
@@ -1141,10 +841,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @return <code>true<code> if success, <code>false</code> otherwise.
* @throws IOException
*/
- private boolean checkInstallResult(String result, Device device, DelayedLaunchInfo launchInfo,
+ private boolean checkInstallResult(String result, IDevice device, DelayedLaunchInfo launchInfo,
String remotePath, InstallRetryMode retryMode) throws IOException {
if (result == null) {
- AdtPlugin.printToConsole(launchInfo.mProject, "Success!");
+ AdtPlugin.printToConsole(launchInfo.getProject(), "Success!");
return true;
} else if (result.equals("INSTALL_FAILED_ALREADY_EXISTS")) { //$NON-NLS-1$
if (retryMode == InstallRetryMode.PROMPT) {
@@ -1153,7 +853,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (prompt) {
retryMode = InstallRetryMode.ALWAYS;
} else {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Installation error! The package already exists.");
return false;
}
@@ -1178,35 +878,35 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}
*/
- AdtPlugin.printToConsole(launchInfo.mProject,
+ AdtPlugin.printToConsole(launchInfo.getProject(),
"Application already exists. Attempting to re-install instead...");
String res = doInstall(launchInfo, remotePath, device, true /* reinstall */);
return checkInstallResult(res, device, launchInfo, remotePath,
InstallRetryMode.NEVER);
}
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Installation error! The package already exists.");
} else if (result.equals("INSTALL_FAILED_INVALID_APK")) { //$NON-NLS-1$
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Installation failed due to invalid APK file!",
"Please check logcat output for more details.");
} else if (result.equals("INSTALL_FAILED_INVALID_URI")) { //$NON-NLS-1$
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Installation failed due to invalid URI!",
"Please check logcat output for more details.");
} else if (result.equals("INSTALL_FAILED_COULDNT_COPY")) { //$NON-NLS-1$
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
String.format("Installation failed: Could not copy %1$s to its final location!",
- launchInfo.mPackageFile.getName()),
+ launchInfo.getPackageFile().getName()),
"Please check logcat output for more details.");
} else if (result.equals("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Re-installation failed due to different application signatures.",
"You must perform a full uninstall of the application. WARNING: This will remove the application data!",
- String.format("Please execute 'adb uninstall %1$s' in a shell.", launchInfo.mPackageName));
+ String.format("Please execute 'adb uninstall %1$s' in a shell.", launchInfo.getPackageName()));
} else {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
String.format("Installation error: %1$s", result),
"Please check logcat output for more details.");
}
@@ -1222,15 +922,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @throws IOException
*/
@SuppressWarnings("unused")
- private String doUninstall(Device device, DelayedLaunchInfo launchInfo) throws IOException {
+ private String doUninstall(IDevice device, DelayedLaunchInfo launchInfo) throws IOException {
InstallReceiver receiver = new InstallReceiver();
try {
- device.executeShellCommand("pm uninstall " + launchInfo.mPackageName, //$NON-NLS-1$
+ device.executeShellCommand("pm uninstall " + launchInfo.getPackageName(), //$NON-NLS-1$
receiver);
} catch (IOException e) {
String msg = String.format(
- "Failed to uninstall %1$s: %2$s", launchInfo.mPackageName, e.getMessage());
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+ "Failed to uninstall %1$s: %2$s", launchInfo.getPackageName(), e.getMessage());
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
throw e;
}
@@ -1248,9 +948,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @throws IOException
*/
private String doInstall(DelayedLaunchInfo launchInfo, final String remotePath,
- final Device device, boolean reinstall) throws IOException {
+ final IDevice device, boolean reinstall) throws IOException {
// kill running application
- Client application = device.getClient(launchInfo.mPackageName);
+ Client application = device.getClient(launchInfo.getPackageName());
if (application != null) {
application.kill();
}
@@ -1264,8 +964,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
} catch (IOException e) {
String msg = String.format(
"Failed to install %1$s on device '%2$s': %3$s",
- launchInfo.mPackageFile.getName(), device.getSerialNumber(), e.getMessage());
- AdtPlugin.printErrorToConsole(launchInfo.mProject, msg);
+ launchInfo.getPackageFile().getName(), device.getSerialNumber(),
+ e.getMessage());
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg);
throw e;
}
@@ -1275,63 +976,29 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
/**
* launches an application on a device or emulator
*
- * @param info the {@link DelayedLaunchInfo} that indicates the activity to launch
+ * @param info the {@link DelayedLaunchInfo} that indicates the launch action
* @param device the device or emulator to launch the application on
*/
- private void launchApp(final DelayedLaunchInfo info, Device device) {
- // if we're not supposed to do anything, just stop the Launch item and return;
- if (info.mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING) {
- String msg = String.format("%1$s installed on device",
- info.mPackageFile.getFullPath().toOSString());
- AdtPlugin.printToConsole(info.mProject, msg, "Done!");
- info.mLaunch.stopLaunch();
- return;
- }
- try {
- String msg = String.format("Starting activity %1$s on device ", info.mActivity,
- info.mDevice);
- AdtPlugin.printToConsole(info.mProject, msg);
-
- // In debug mode, we need to add the info to the list of application monitoring
- // client changes.
- if (info.mDebugMode) {
- synchronized (sListLock) {
- if (mWaitingForDebuggerApplications.contains(info) == false) {
- mWaitingForDebuggerApplications.add(info);
- }
+ public void launchApp(final DelayedLaunchInfo info, IDevice device) {
+ if (info.isDebugMode()) {
+ synchronized (sListLock) {
+ if (mWaitingForDebuggerApplications.contains(info) == false) {
+ mWaitingForDebuggerApplications.add(info);
}
}
-
- // increment launch attempt count, to handle retries and timeouts
- info.mAttemptCount++;
-
- // now we actually launch the app.
- device.executeShellCommand("am start" //$NON-NLS-1$
- + (info.mDebugMode ? " -D" //$NON-NLS-1$
- : "") //$NON-NLS-1$
- + " -n " //$NON-NLS-1$
- + info.mPackageName + "/" //$NON-NLS-1$
- + info.mActivity.replaceAll("\\$", "\\\\\\$"), //$NON-NLS-1$ //$NON-NLS-2$
- new AMReceiver(info, device));
-
+ }
+ if (info.getLaunchAction().doLaunchAction(info, device)) {
// if the app is not a debug app, we need to do some clean up, as
// the process is done!
- if (info.mDebugMode == false) {
+ if (info.isDebugMode() == false) {
// stop the launch object, since there's no debug, and it can't
// provide any control over the app
- info.mLaunch.stopLaunch();
+ stopLaunch(info);
}
- } catch (IOException e) {
- // something went wrong trying to launch the app.
+ } else {
+ // something went wrong or no further launch action needed
// lets stop the Launch
- AdtPlugin.printErrorToConsole(info.mProject,
- String.format("Launch error: %s", e.getMessage()));
- info.mLaunch.stopLaunch();
-
- // and remove it from the list of app waiting for debuggers
- synchronized (sListLock) {
- mWaitingForDebuggerApplications.remove(info);
- }
+ stopLaunch(info);
}
}
@@ -1339,7 +1006,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// split the custom command line in segments
ArrayList<String> customArgs = new ArrayList<String>();
- boolean has_wipe_data = false;
+ boolean hasWipeData = false;
if (config.mEmulatorCommandLine != null && config.mEmulatorCommandLine.length() > 0) {
String[] segments = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$
@@ -1347,17 +1014,17 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
for (String s : segments) {
if (s.length() > 0) {
customArgs.add(s);
- if (!has_wipe_data && s.equals(FLAG_WIPE_DATA)) {
- has_wipe_data = true;
+ if (!hasWipeData && s.equals(FLAG_WIPE_DATA)) {
+ hasWipeData = true;
}
}
}
}
- boolean needs_wipe_data = config.mWipeData && !has_wipe_data;
- if (needs_wipe_data) {
+ boolean needsWipeData = config.mWipeData && !hasWipeData;
+ if (needsWipeData) {
if (!AdtPlugin.displayPrompt("Android Launch", "Are you sure you want to wipe all user data when starting this emulator?")) {
- needs_wipe_data = false;
+ needsWipeData = false;
}
}
@@ -1378,7 +1045,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
list.add(config.mNetworkDelay);
}
- if (needs_wipe_data) {
+ if (needsWipeData) {
list.add(FLAG_WIPE_DATA);
}
@@ -1482,7 +1149,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param monitor A Progress monitor
* @see #connectRemoteDebugger(int, AndroidLaunch, IProgressMonitor)
*/
- public static void launchRemoteDebugger( final int debugPort, final AndroidLaunch androidLaunch,
+ public static void launchRemoteDebugger(final int debugPort, final AndroidLaunch androidLaunch,
final IProgressMonitor monitor) {
new Thread("Debugger connection") { //$NON-NLS-1$
@Override
@@ -1507,26 +1174,18 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
*/
public void bridgeChanged(AndroidDebugBridge bridge) {
// The adb server has changed. We cancel any pending launches.
- String message1 = "adb server change: cancelling '%1$s' launch!";
- String message2 = "adb server change: cancelling sync!";
+ String message = "adb server change: cancelling '%1$s'!";
synchronized (sListLock) {
for (DelayedLaunchInfo launchInfo : mWaitingForReadyEmulatorList) {
- if (launchInfo.mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, message2);
- } else {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
- String.format(message1, launchInfo.mActivity));
- }
- launchInfo.mLaunch.stopLaunch();
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
+ String.format(message, launchInfo.getLaunchAction().getLaunchDescription()));
+ stopLaunch(launchInfo);
}
for (DelayedLaunchInfo launchInfo : mWaitingForDebuggerApplications) {
- if (launchInfo.mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING) {
- AdtPlugin.printErrorToConsole(launchInfo.mProject, message2);
- } else {
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
- String.format(message1, launchInfo.mActivity));
- }
- launchInfo.mLaunch.stopLaunch();
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
+ String.format(message,
+ launchInfo.getLaunchAction().getLaunchDescription()));
+ stopLaunch(launchInfo);
}
mWaitingForReadyEmulatorList.clear();
@@ -1552,15 +1211,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
mWaitingForEmulatorLaunches.remove(0);
// give the launch item its device for later use.
- launchInfo.mDevice = device;
+ launchInfo.setDevice(device);
// and move it to the other list
mWaitingForReadyEmulatorList.add(launchInfo);
// and tell the user about it
- AdtPlugin.printToConsole(launchInfo.mProject,
+ AdtPlugin.printToConsole(launchInfo.getProject(),
String.format("New emulator found: %1$s", device.getSerialNumber()));
- AdtPlugin.printToConsole(launchInfo.mProject,
+ AdtPlugin.printToConsole(launchInfo.getProject(),
String.format("Waiting for HOME ('%1$s') to be launched...",
AdtPlugin.getDefault().getPreferenceStore().getString(
AdtPlugin.PREFS_HOME_PACKAGE)));
@@ -1579,25 +1238,25 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
@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!";
+ String message = "%1$s disconnected! Cancelling '%2$s'!";
synchronized (sListLock) {
ArrayList<DelayedLaunchInfo> copyList =
- (ArrayList<DelayedLaunchInfo>)mWaitingForReadyEmulatorList.clone();
+ (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);
+ if (launchInfo.getDevice() == device) {
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
+ String.format(message, device.getSerialNumber(),
+ launchInfo.getLaunchAction().getLaunchDescription()));
+ stopLaunch(launchInfo);
}
}
- copyList = (ArrayList<DelayedLaunchInfo>)mWaitingForDebuggerApplications.clone();
+ 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);
+ if (launchInfo.getDevice() == device) {
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
+ String.format(message, device.getSerialNumber(),
+ launchInfo.getLaunchAction().getLaunchDescription()));
+ stopLaunch(launchInfo);
}
}
}
@@ -1641,13 +1300,13 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
if (home.equals(applicationName)) {
// looks like home is up, get its device
- Device device = client.getDevice();
+ IDevice device = client.getDevice();
// look for application waiting for home
synchronized (sListLock) {
- for (int i = 0 ; i < mWaitingForReadyEmulatorList.size() ;) {
+ for (int i = 0; i < mWaitingForReadyEmulatorList.size(); ) {
DelayedLaunchInfo launchInfo = mWaitingForReadyEmulatorList.get(i);
- if (launchInfo.mDevice == device) {
+ if (launchInfo.getDevice() == device) {
// it's match, remove from the list
mWaitingForReadyEmulatorList.remove(i);
@@ -1657,13 +1316,13 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// so we check now
if (checkBuildInfo(launchInfo, device) == false) {
// device is not the proper API!
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Launch canceled!");
- launchInfo.mLaunch.stopLaunch();
+ stopLaunch(launchInfo);
return;
}
- AdtPlugin.printToConsole(launchInfo.mProject,
+ AdtPlugin.printToConsole(launchInfo.getProject(),
String.format("HOME is up on device '%1$s'",
device.getSerialNumber()));
@@ -1673,9 +1332,9 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
launchApp(launchInfo, device);
} else {
// failure! Cancel and return
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
"Launch canceled!");
- launchInfo.mLaunch.stopLaunch();
+ stopLaunch(launchInfo);
}
break;
@@ -1727,18 +1386,18 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
String applicationName = client.getClientData().getClientDescription();
Log.d("adt", "App Name: " + applicationName);
synchronized (sListLock) {
- for (int i = 0 ; i < mWaitingForDebuggerApplications.size() ;) {
+ for (int i = 0; i < mWaitingForDebuggerApplications.size(); ) {
final DelayedLaunchInfo launchInfo = mWaitingForDebuggerApplications.get(i);
- if (client.getDevice() == launchInfo.mDevice &&
- applicationName.equals(launchInfo.mPackageName)) {
+ if (client.getDevice() == launchInfo.getDevice() &&
+ applicationName.equals(launchInfo.getPackageName())) {
// this is a match. We remove the launch info from the list
mWaitingForDebuggerApplications.remove(i);
// and connect the debugger.
String msg = String.format(
"Attempting to connect debugger to '%1$s' on port %2$d",
- launchInfo.mPackageName, client.getDebuggerListenPort());
- AdtPlugin.printToConsole(launchInfo.mProject, msg);
+ launchInfo.getPackageName(), client.getDebuggerListenPort());
+ AdtPlugin.printToConsole(launchInfo.getProject(), msg);
new Thread("Debugger Connection") { //$NON-NLS-1$
@Override
@@ -1746,18 +1405,19 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
try {
if (connectRemoteDebugger(
client.getDebuggerListenPort(),
- launchInfo.mLaunch, launchInfo.mMonitor) == false) {
+ launchInfo.getLaunch(),
+ launchInfo.getMonitor()) == false) {
return;
}
} catch (CoreException e) {
// well something went wrong.
- AdtPlugin.printErrorToConsole(launchInfo.mProject,
+ AdtPlugin.printErrorToConsole(launchInfo.getProject(),
String.format("Launch error: %s", e.getMessage()));
// stop the launch
- launchInfo.mLaunch.stopLaunch();
+ stopLaunch(launchInfo);
}
- launchInfo.mMonitor.done();
+ launchInfo.getMonitor().done();
}
}.start();
@@ -1833,4 +1493,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
}.start();
}
+ /* (non-Javadoc)
+ * @see com.android.ide.eclipse.adt.launch.ILaunchController#stopLaunch(com.android.ide.eclipse.adt.launch.AndroidLaunchController.DelayedLaunchInfo)
+ */
+ public void stopLaunch(DelayedLaunchInfo launchInfo) {
+ launchInfo.getLaunch().stopLaunch();
+ synchronized (sListLock) {
+ mWaitingForReadyEmulatorList.remove(launchInfo);
+ mWaitingForDebuggerApplications.remove(launchInfo);
+ }
+ }
}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
new file mode 100644
index 0000000..a59518c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import com.android.ddmlib.IDevice;
+
+/**
+ * A delayed launch waiting for a device to be present or ready before the
+ * application is launched.
+ */
+public final class DelayedLaunchInfo {
+
+ /**
+ * Used to indicate behavior when Android app already exists
+ */
+ enum InstallRetryMode {
+ NEVER, ALWAYS, PROMPT;
+ }
+
+ /** The device on which to launch the app */
+ private IDevice mDevice = null;
+
+ /** The eclipse project */
+ private final IProject mProject;
+
+ /** Package name */
+ private final String mPackageName;
+
+ /** IFile to the package (.apk) file */
+ private final IFile mPackageFile;
+
+ /** debuggable attribute of the manifest file. */
+ private final Boolean mDebuggable;
+
+ /** Required ApiVersionNumber by the app. 0 means no requirements */
+ private final int mRequiredApiVersionNumber;
+
+ private InstallRetryMode mRetryMode = InstallRetryMode.NEVER;
+
+ /** Launch action. */
+ private final IAndroidLaunchAction mLaunchAction;
+
+ /** the launch object */
+ private final AndroidLaunch mLaunch;
+
+ /** the monitor object */
+ private final IProgressMonitor mMonitor;
+
+ /** debug mode flag */
+ private boolean mDebugMode;
+
+ /** current number of launch attempts */
+ private int mAttemptCount = 0;
+
+ /** cancellation state of launch */
+ private boolean mCancelled = false;
+
+ /**
+ * Basic constructor with activity and package info.
+ *
+ * @param project the eclipse project that corresponds to Android app
+ * @param packageName package name of Android app
+ * @param launchAction action to perform after app install
+ * @param pack IFile to the package (.apk) file
+ * @param debuggable debuggable attribute of the app's manifest file.
+ * @param requiredApiVersionNumber required SDK version by the app. 0 means no requirements.
+ * @param launch the launch object
+ * @param monitor progress monitor for launch
+ */
+ public DelayedLaunchInfo(IProject project, String packageName,
+ IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
+ int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
+ mProject = project;
+ mPackageName = packageName;
+ mPackageFile = pack;
+ mLaunchAction = launchAction;
+ mLaunch = launch;
+ mMonitor = monitor;
+ mDebuggable = debuggable;
+ mRequiredApiVersionNumber = requiredApiVersionNumber;
+ }
+
+ /**
+ * @return the device on which to launch the app
+ */
+ public IDevice getDevice() {
+ return mDevice;
+ }
+
+ /**
+ * Set the device on which to launch the app
+ */
+ public void setDevice(IDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * @return the eclipse project that corresponds to Android app
+ */
+ public IProject getProject() {
+ return mProject;
+ }
+
+ /**
+ * @return the package name of the Android app
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * @return the application package file
+ */
+ public IFile getPackageFile() {
+ return mPackageFile;
+ }
+
+ /**
+ * @return true if Android app is marked as debuggable in its manifest
+ */
+ public Boolean getDebuggable() {
+ return mDebuggable;
+ }
+
+ /**
+ * @return the required api version number for the Android app
+ */
+ public int getRequiredApiVersionNumber() {
+ return mRequiredApiVersionNumber;
+ }
+
+ /**
+ * @param retryMode the install retry mode to set
+ */
+ public void setRetryMode(InstallRetryMode retryMode) {
+ this.mRetryMode = retryMode;
+ }
+
+ /**
+ * @return the installation retry mode
+ */
+ public InstallRetryMode getRetryMode() {
+ return mRetryMode;
+ }
+
+ /**
+ * @return the launch action
+ */
+ public IAndroidLaunchAction getLaunchAction() {
+ return mLaunchAction;
+ }
+
+ /**
+ * @return the launch
+ */
+ public AndroidLaunch getLaunch() {
+ return mLaunch;
+ }
+
+ /**
+ * @return the launch progress monitor
+ */
+ public IProgressMonitor getMonitor() {
+ return mMonitor;
+ }
+
+ /**
+ * @param debugMode the debug mode to set
+ */
+ public void setDebugMode(boolean debugMode) {
+ this.mDebugMode = debugMode;
+ }
+
+ /**
+ * @return true if this is a debug launch
+ */
+ public boolean isDebugMode() {
+ return mDebugMode;
+ }
+
+ /**
+ * Increases the number of launch attempts
+ */
+ public void incrementAttemptCount() {
+ mAttemptCount++;
+ }
+
+ /**
+ * @return the number of launch attempts made
+ */
+ public int getAttemptCount() {
+ return mAttemptCount;
+ }
+
+ /**
+ * Set if launch has been cancelled
+ */
+ public void setCancelled(boolean cancelled) {
+ this.mCancelled = cancelled;
+ }
+
+ /**
+ * @return true if launch has been cancelled
+ */
+ public boolean isCancelled() {
+ return mCancelled;
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
index a960bda..13bb83a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
@@ -231,9 +231,9 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
public static class DeviceChooserResponse {
private AvdInfo mAvdToLaunch;
- private Device mDeviceToUse;
+ private IDevice mDeviceToUse;
- public void setDeviceToUse(Device d) {
+ public void setDeviceToUse(IDevice d) {
mDeviceToUse = d;
mAvdToLaunch = null;
}
@@ -243,7 +243,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
mDeviceToUse = null;
}
- public Device getDeviceToUse() {
+ public IDevice getDeviceToUse() {
return mDeviceToUse;
}
@@ -737,3 +737,4 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener
mDisableAvdSelectionChange = false;
}
}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmptyLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmptyLaunchAction.java
new file mode 100644
index 0000000..02ae675
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmptyLaunchAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ddmlib.IDevice;
+import com.android.ide.eclipse.adt.AdtPlugin;
+
+/**
+ * A launch action that does nothing after the application has been installed
+ */
+public class EmptyLaunchAction implements IAndroidLaunchAction {
+
+ public boolean doLaunchAction(DelayedLaunchInfo info, IDevice device) {
+ // we're not supposed to do anything, just return;
+ String msg = String.format("%1$s installed on device",
+ info.getPackageFile().getFullPath().toOSString());
+ AdtPlugin.printToConsole(info.getProject(), msg, "Done!");
+ // return false so launch controller will not wait for debugger to attach
+ return false;
+ }
+
+ public String getLaunchDescription() {
+ return "sync";
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/IAndroidLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/IAndroidLaunchAction.java
new file mode 100644
index 0000000..2f3cb89
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/IAndroidLaunchAction.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ddmlib.IDevice;
+import com.android.ide.eclipse.adt.launch.DelayedLaunchInfo;
+
+/**
+ * An action to perform after performing a launch of an Android application
+ */
+public interface IAndroidLaunchAction {
+
+ /**
+ * Do the launch
+ *
+ * @param info the {@link DelayedLaunchInfo} that contains launch details
+ * @param device the Android device to perform action on
+ * @returns true if launch was successfully, and controller should wait for debugger to attach
+ * (if applicable)
+ */
+ boolean doLaunchAction(DelayedLaunchInfo info, IDevice device);
+
+ /**
+ * Return a description of launch, to be used for logging and error messages
+ */
+ String getLaunchDescription();
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ILaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ILaunchController.java
new file mode 100644
index 0000000..2372c2d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/ILaunchController.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ddmlib.IDevice;
+
+/**
+ * Interface for managing Android launches
+ */
+public interface ILaunchController {
+
+ /**
+ * Launches an application on a device or emulator
+ *
+ * @param launchInfo the {@link DelayedLaunchInfo} that indicates the launch action
+ * @param device the device or emulator to launch the application on
+ */
+ public void launchApp(DelayedLaunchInfo launchInfo, IDevice device);
+
+ /**
+ * Cancels a launch
+ *
+ * @param launchInfo the {@link DelayedLaunchInfo} to cancel
+ */
+ void stopLaunch(DelayedLaunchInfo launchInfo);
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
index a46f56c..80f62ea 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
@@ -18,7 +18,6 @@ package com.android.ide.eclipse.adt.launch;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.launch.AndroidLaunchController.AndroidLaunchConfiguration;
import com.android.ide.eclipse.adt.project.ProjectHelper;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
@@ -233,7 +232,16 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
return;
}
- String activityName = null;
+ doLaunch(configuration, mode, monitor, project, androidLaunch, config, controller,
+ applicationPackage, manifestParser);
+ }
+
+ protected void doLaunch(ILaunchConfiguration configuration, String mode,
+ IProgressMonitor monitor, IProject project, AndroidLaunch androidLaunch,
+ AndroidLaunchConfiguration config, AndroidLaunchController controller,
+ IFile applicationPackage, AndroidManifestParser manifestParser) {
+
+ String activityName = null;
if (config.mLaunchAction == ACTION_ACTIVITY) {
// Get the activity name defined in the config
@@ -292,11 +300,16 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
}
}
+ IAndroidLaunchAction launchAction = new EmptyLaunchAction();
+ if (activityName != null) {
+ launchAction = new ActivityLaunchAction(activityName, controller);
+ }
+
// everything seems fine, we ask the launch controller to handle
// the rest
controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
- activityName, config, androidLaunch, monitor);
+ launchAction, config, androidLaunch, monitor);
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
index fd0c045..c650b98 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/ProjectHelper.java
@@ -400,6 +400,9 @@ public final class ProjectHelper {
try {
parser = AndroidManifestParser.parseForData(manifestFile);
} catch (CoreException e) {
+ // ignore, handled below.
+ }
+ if (parser == null) {
// skip this project.
continue;
}
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 d686830..5aeb335 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
@@ -253,8 +253,7 @@ public class AndroidClasspathContainerInitializer extends ClasspathContainerInit
if (markerMessage != null) {
// log the error and put the marker on the project if we can.
if (outputToConsole) {
- AdtPlugin.printBuildToConsole(AdtConstants.BUILD_ALWAYS, iProject,
- markerMessage);
+ AdtPlugin.printErrorToConsole(iProject, markerMessage);
}
try {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
index 6c4f4ba..0dd88c0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newproject/NewProjectCreationPage.java
@@ -36,7 +36,6 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
@@ -823,12 +822,7 @@ public class NewProjectCreationPage extends WizardPage {
Path path = new Path(f.getPath());
String osPath = path.append(AndroidConstants.FN_ANDROID_MANIFEST).toOSString();
- AndroidManifestParser manifestData = null;
- try {
- manifestData = AndroidManifestParser.parseForData(osPath);
- } catch (CoreException e1) {
- // ignore any parsing issue
- }
+ AndroidManifestParser manifestData = AndroidManifestParser.parseForData(osPath);
if (manifestData == null) {
return;
}
@@ -1096,10 +1090,8 @@ public class NewProjectCreationPage extends WizardPage {
}
// Parse it and check the important fields.
- AndroidManifestParser manifestData;
- try {
- manifestData = AndroidManifestParser.parseForData(osPath);
- } catch (CoreException e) {
+ AndroidManifestParser manifestData = AndroidManifestParser.parseForData(osPath);
+ if (manifestData == null) {
return setStatus(
String.format("File %1$s could not be parsed.", osPath),
MSG_ERROR);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index b2817ff..0a45196 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -686,7 +686,8 @@ public class AndroidManifestParser {
* Parses the manifest file, and collects data.
* @param manifestFile The manifest file to parse.
* @return an {@link AndroidManifestParser} or null if the parsing failed.
- * @throws CoreException
+ * @throws CoreException for example the file does not exist in the workspace or
+ * the workspace needs to be refreshed.
*/
public static AndroidManifestParser parseForData(IFile manifestFile) throws CoreException {
return parse(null /* javaProject */, manifestFile, null /* errorListener */,
@@ -698,11 +699,15 @@ public class AndroidManifestParser {
*
* @param osManifestFilePath The OS path of the manifest file to parse.
* @return an {@link AndroidManifestParser} or null if the parsing failed.
- * @throws CoreException
*/
- public static AndroidManifestParser parseForData(String osManifestFilePath)
- throws CoreException {
- return parse(new File(osManifestFilePath));
+ public static AndroidManifestParser parseForData(String osManifestFilePath) {
+ try {
+ return parse(new File(osManifestFilePath));
+ } catch (CoreException e) {
+ // Ignore workspace errors (unlikely to happen since this parses an actual file,
+ // not a workspace resource).
+ return null;
+ }
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/AbstractGraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/AbstractGraphicalLayoutEditor.java
new file mode 100644
index 0000000..0499867
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/AbstractGraphicalLayoutEditor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.editors.layout;
+
+import com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListener;
+import com.android.ide.eclipse.editors.layout.parts.ElementCreateCommand;
+import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration;
+import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
+import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+
+import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
+import org.eclipse.gef.ui.parts.SelectionSynchronizer;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Abstract GraphicalLayoutEditor.
+ */
+/*package*/ abstract class AbstractGraphicalLayoutEditor extends GraphicalEditorWithPalette
+ implements IWorkbenchPart, ILayoutReloadListener {
+
+ /**
+ * Sets the UI for the edition of a new file.
+ * @param configuration the configuration of the new file.
+ */
+ abstract void editNewFile(FolderConfiguration configuration);
+
+ /**
+ * Reloads this editor, by getting the new model from the {@link LayoutEditor}.
+ */
+ abstract void reloadEditor();
+
+ /**
+ * Callback for XML model changed. Only update/recompute the layout if the editor is visible
+ */
+ abstract void onXmlModelChanged();
+
+ /**
+ * Responds to a page change that made the Graphical editor page the activated page.
+ */
+ abstract void activated();
+
+ /**
+ * Responds to a page change that made the Graphical editor page the deactivated page
+ */
+ abstract void deactivated();
+
+ /**
+ * Used by LayoutEditor.UiEditorActions.selectUiNode to select a new UI Node
+ * created by {@link ElementCreateCommand#execute()}.
+ *
+ * @param uiNodeModel The {@link UiElementNode} to select.
+ */
+ abstract void selectModel(UiElementNode uiNodeModel);
+
+ /**
+ * Returns the selection synchronizer object.
+ * The synchronizer can be used to sync the selection of 2 or more EditPartViewers.
+ * <p/>
+ * This is changed from protected to public so that the outline can use it.
+ *
+ * @return the synchronizer
+ */
+ @Override
+ public SelectionSynchronizer getSelectionSynchronizer() {
+ return super.getSelectionSynchronizer();
+ }
+
+ /**
+ * Returns the edit domain.
+ * <p/>
+ * This is changed from protected to public so that the outline can use it.
+ *
+ * @return the edit domain
+ */
+ @Override
+ public DefaultEditDomain getEditDomain() {
+ return super.getEditDomain();
+ }
+
+ abstract void reloadPalette();
+
+ abstract void recomputeLayout();
+
+ abstract UiDocumentNode getModel();
+
+ abstract LayoutEditor getLayoutEditor();
+
+ abstract Clipboard getClipboard();
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
index eb7dee6..9c529e5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/GraphicalLayoutEditor.java
@@ -86,8 +86,6 @@ import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.requests.CreationFactory;
-import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
-import org.eclipse.gef.ui.parts.SelectionSynchronizer;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
@@ -141,7 +139,7 @@ import java.util.Set;
* <p/>
* To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html
*/
-public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
+public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor
implements ILayoutReloadListener {
private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$
@@ -595,6 +593,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
return mPaletteRoot;
}
+ @Override
public Clipboard getClipboard() {
return mClipboard;
}
@@ -716,7 +715,8 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
*
* @param uiNodeModel The {@link UiElementNode} to select.
*/
- public void selectModel(UiElementNode uiNodeModel) {
+ @Override
+ void selectModel(UiElementNode uiNodeModel) {
GraphicalViewer viewer = getGraphicalViewer();
// Give focus to the graphical viewer (in case the outline has it)
@@ -734,6 +734,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
// Local methods
//--------------
+ @Override
public LayoutEditor getLayoutEditor() {
return mLayoutEditor;
}
@@ -863,7 +864,8 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
* Sets the UI for the edition of a new file.
* @param configuration the configuration of the new file.
*/
- public void editNewFile(FolderConfiguration configuration) {
+ @Override
+ void editNewFile(FolderConfiguration configuration) {
// update the configuration UI
setConfiguration(configuration);
@@ -1015,6 +1017,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
/**
* Reloads this editor, by getting the new model from the {@link LayoutEditor}.
*/
+ @Override
void reloadEditor() {
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(getModel());
@@ -1036,6 +1039,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
/**
* Callback for XML model changed. Only update/recompute the layout if the editor is visible
*/
+ @Override
void onXmlModelChanged() {
if (mLayoutEditor.isGraphicalEditorActive()) {
doXmlReload(true /* force */);
@@ -1265,10 +1269,12 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
}
+ @Override
UiDocumentNode getModel() {
return mLayoutEditor.getUiRootNode();
}
+ @Override
void reloadPalette() {
PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData());
}
@@ -1667,6 +1673,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
/**
* Recomputes the layout with the help of layoutlib.
*/
+ @Override
@SuppressWarnings("deprecation")
void recomputeLayout() {
doXmlReload(false /* force */);
@@ -1968,6 +1975,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
/**
* Responds to a page change that made the Graphical editor page the activated page.
*/
+ @Override
void activated() {
if (mNeedsRecompute || mNeedsXmlReload) {
recomputeLayout();
@@ -1977,6 +1985,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
/**
* Responds to a page change that made the Graphical editor page the deactivated page
*/
+ @Override
void deactivated() {
// nothing to be done here for now.
}
@@ -2234,31 +2243,6 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
}
/**
- * Returns the selection synchronizer object.
- * The synchronizer can be used to sync the selection of 2 or more EditPartViewers.
- * <p/>
- * This is changed from protected to public so that the outline can use it.
- *
- * @return the synchronizer
- */
- @Override
- public SelectionSynchronizer getSelectionSynchronizer() {
- return super.getSelectionSynchronizer();
- }
-
- /**
- * Returns the edit domain.
- * <p/>
- * This is changed from protected to public so that the outline can use it.
- *
- * @return the edit domain
- */
- @Override
- public DefaultEditDomain getEditDomain() {
- return super.getEditDomain();
- }
-
- /**
* Creates a new layout file from the specificed {@link FolderConfiguration}.
*/
private void createAlternateLayout(final FolderConfiguration config) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
index dabe797..f3a5113 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/LayoutEditor.java
@@ -55,7 +55,7 @@ public class LayoutEditor extends AndroidEditor implements IShowEditorInput, IPa
/** Root node of the UI element hierarchy */
private UiDocumentNode mUiRootNode;
- private GraphicalLayoutEditor mGraphicalEditor;
+ private AbstractGraphicalLayoutEditor mGraphicalEditor;
private int mGraphicalEditorIndex;
/** Implementation of the {@link IContentOutlinePage} for this editor */
private UiContentOutlinePage mOutline;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
index 3e0f5d8..536e902 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/UiContentOutlinePage.java
@@ -70,7 +70,7 @@ import java.util.List;
*/
class UiContentOutlinePage extends ContentOutlinePage {
- private GraphicalLayoutEditor mEditor;
+ private AbstractGraphicalLayoutEditor mEditor;
private Action mAddAction;
private Action mDeleteAction;
@@ -79,7 +79,7 @@ class UiContentOutlinePage extends ContentOutlinePage {
private UiOutlineActions mUiActions = new UiOutlineActions();
- public UiContentOutlinePage(GraphicalLayoutEditor editor, final EditPartViewer viewer) {
+ public UiContentOutlinePage(AbstractGraphicalLayoutEditor editor, final EditPartViewer viewer) {
super(viewer);
mEditor = editor;
IconFactory factory = IconFactory.getInstance();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
index c3f4dd8..5726d78 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/layout/descriptors/LayoutDescriptors.java
@@ -18,7 +18,6 @@ package com.android.ide.eclipse.editors.layout.descriptors;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
-import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.common.resources.ViewClassInfo;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeInfo;
import com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfo;
@@ -27,7 +26,6 @@ import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
-import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.sdklib.SdkConstants;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
index fa09305..2d14c06 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/resources/manager/CompiledResourcesMonitor.java
@@ -217,8 +217,10 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi
try {
IFile manifestFile = AndroidManifestParser.getManifest(project);
AndroidManifestParser data = AndroidManifestParser.parseForData(manifestFile);
- String javaPackage = data.getPackage();
- return javaPackage + ".R"; //$NON-NLS-1$
+ if (data != null) {
+ String javaPackage = data.getPackage();
+ return javaPackage + ".R"; //$NON-NLS-1$
+ }
} catch (CoreException e) {
// This will typically happen either because the manifest file is not present
// and/or the workspace needs to be refreshed.
@@ -227,8 +229,8 @@ public final class CompiledResourcesMonitor implements IFileListener, IProjectLi
"Failed to find the package of the AndroidManifest of project %1$s. Reason: %2$s",
project.getName(),
e.getMessage());
- return null;
}
+ return null;
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
index 48f8a7f..32cac9f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/uimodel/UiResourceAttributeNode.java
@@ -158,6 +158,35 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
return null;
}
+ /**
+ * Gets all the values one could use to auto-complete a "resource" value in an XML
+ * content assist.
+ * <p/>
+ * Typically the user is editing the value of an attribute in a resource XML, e.g.
+ * <pre> "&lt;Button android:test="@string/my_[caret]_string..." </pre>
+ * <p/>
+ *
+ * "prefix" is the value that the user has typed so far (or more exactly whatever is on the
+ * left side of the insertion point). In the example above it would be "@style/my_".
+ * <p/>
+ *
+ * To avoid a huge long list of values, the completion works on two levels:
+ * <ul>
+ * <li> If a resource type as been typed so far (e.g. "@style/"), then limit the values to
+ * the possible completions that match this type.
+ * <li> If no resource type as been typed so far, then return the various types that could be
+ * completed. So if the project has only strings and layouts resources, for example,
+ * the returned list will only include "@string/" and "@layout/".
+ * </ul>
+ *
+ * Finally if anywhere in the string we find the special token "android:", we use the
+ * current framework system resources rather than the project resources.
+ * This works for both "@android:style/foo" and "@style/android:foo" conventions even though
+ * the reconstructed name will always be of the former form.
+ *
+ * Note that "android:" here is a keyword specific to Android resources and should not be
+ * mixed with an XML namespace for an XML attribute name.
+ */
@Override
public String[] getPossibleValues(String prefix) {
IResourceRepository repository = null;
@@ -174,6 +203,8 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
}
} else {
// If there's a prefix with "android:" in it, use the system resources
+ //
+ // TODO find a way to only list *public* framework resources here.
AndroidTargetData data = editor.getTargetData();
repository = data.getSystemResources();
isSystem = true;
diff --git a/scripts/android_rules.xml b/scripts/android_rules.xml
index 799aa0b..aad9dbd 100644
--- a/scripts/android_rules.xml
+++ b/scripts/android_rules.xml
@@ -28,6 +28,7 @@
<!-- Input directories -->
<property name="source-folder" value="src" />
+ <property name="gen-folder" value="gen" />
<property name="resource-folder" value="res" />
<property name="asset-folder" value="assets" />
<property name="source-location" value="${basedir}/${source-folder}" />
@@ -39,6 +40,7 @@
<property name="native-libs-folder" value="libs" />
<!-- Output directories -->
+ <property name="gen-folder" value="gen" />
<property name="out-folder" value="bin" />
<property name="out-classes" value="${out-folder}/classes" />
<property name="out-classes-location" value="${basedir}/${out-classes}"/>
@@ -46,9 +48,6 @@
<property name="main-out-folder" value="../${out-folder}" />
<property name="main-out-classes" value="${main-out-folder}/classes"/>
- <!-- Create R.java in the source directory -->
- <property name="r-folder" value="${source-folder}" />
-
<!-- Intermediate files -->
<property name="dex-file" value="classes.dex" />
<property name="intermediate-dex" value="${out-folder}/${dex-file}" />
@@ -73,6 +72,8 @@
<!-- Create the output directories if they don't exist yet. -->
<target name="dirs">
<echo>Creating output directories if needed...</echo>
+ <mkdir dir="${external-libs-folder}" />
+ <mkdir dir="${gen-folder}" />
<mkdir dir="${out-folder}" />
<mkdir dir="${out-classes}" />
</target>
@@ -84,7 +85,7 @@
<arg value="package" />
<arg value="-m" />
<arg value="-J" />
- <arg path="${r-folder}" />
+ <arg path="${gen-folder}" />
<arg value="-M" />
<arg path="AndroidManifest.xml" />
<arg value="-S" />
@@ -100,6 +101,7 @@
<apply executable="${aidl}" failonerror="true">
<arg value="-p${android-aidl}" />
<arg value="-I${source-folder}" />
+ <arg value="-o${gen-folder}" />
<fileset dir="${source-folder}">
<include name="**/*.aidl"/>
</fileset>
@@ -107,11 +109,12 @@
</target>
<!-- Compile this project's .java files into .class files. -->
- <target name="compile" depends="dirs, resource-src, aidl">
+ <target name="compile" depends="resource-src, aidl">
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
- srcdir="${source-folder}"
destdir="${out-classes}"
bootclasspathref="android.target.classpath">
+ <src path="${source-folder}" />
+ <src path="${gen-folder}" />
<classpath>
<fileset dir="${external-libs-folder}" includes="*.jar"/>
<pathelement path="${main-out-classes}"/>