FileDocCategorySizeDatePackage
LaunchConfigDelegate.javaAPI DocAndroid 1.5 API17994Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.adt.launch

LaunchConfigDelegate

public class LaunchConfigDelegate extends org.eclipse.debug.core.model.LaunchConfigurationDelegate
Implementation of an eclipse LauncConfigurationDelegate to launch android application in debug.

Fields Summary
static final int
INVALID_DEBUG_PORT
public static final String
ANDROID_LAUNCH_TYPE_ID
public static final String
ATTR_TARGET_MODE
Target mode parameters: true is automatic, false is manual
public static final com.android.ide.eclipse.adt.launch.AndroidLaunchConfiguration.TargetMode
DEFAULT_TARGET_MODE
public static final String
ATTR_LAUNCH_ACTION
Launch action:
  • 0: launch default activity
  • 1: launch specified activity. See {@link #ATTR_ACTIVITY}
  • 2: Do Nothing
public static final int
ACTION_DEFAULT
Default launch action. This launches the activity that is setup to be found in the HOME screen.
public static final int
ACTION_ACTIVITY
Launch action starting a specific activity.
public static final int
ACTION_DO_NOTHING
Launch action that does nothing.
public static final int
DEFAULT_LAUNCH_ACTION
Default launch action value.
public static final String
ATTR_ACTIVITY
Activity to be launched if {@link #ATTR_LAUNCH_ACTION} is 1
public static final String
ATTR_AVD_NAME
public static final String
ATTR_SPEED
public static final int
DEFAULT_SPEED
Index of the default network speed setting for the emulator.
Get the emulator option with EmulatorConfigTab.getSpeed(index)
public static final String
ATTR_DELAY
public static final int
DEFAULT_DELAY
Index of the default network latency setting for the emulator.
Get the emulator option with EmulatorConfigTab.getDelay(index)
public static final String
ATTR_COMMANDLINE
public static final String
ATTR_WIPE_DATA
public static final boolean
DEFAULT_WIPE_DATA
public static final String
ATTR_NO_BOOT_ANIM
public static final boolean
DEFAULT_NO_BOOT_ANIM
public static final String
ATTR_DEBUG_PORT
Constructors Summary
Methods Summary
public booleanbuildForLaunch(org.eclipse.debug.core.ILaunchConfiguration configuration, java.lang.String mode, org.eclipse.core.runtime.IProgressMonitor monitor)


        // need to check we have everything
        IProject project = getProject(configuration);

        if (project != null) {
            // force an incremental build to be sure the resources will
            // be updated if they were not saved before the launch was launched.
            return true;
        }

        throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
                        1 /* code, unused */, "Can't find the project!", null /* exception */));
    
private booleancheckAndroidProject(org.eclipse.core.resources.IProject project)
Checks the project is an android project.

param
project The project to check
return
true if the project is an android SDK.
throws
CoreException

        // check if the project is a java and an android project.
        if (project.hasNature(JavaCore.NATURE_ID) == false) {
            String msg = String.format("%1$s is not a Java project!", project.getName());
            AdtPlugin.displayError("Android Launch", msg);
            return false;
        }

        if (project.hasNature(AndroidConstants.NATURE) == false) {
            String msg = String.format("%1$s is not an Android project!", project.getName());
            AdtPlugin.displayError("Android Launch", msg);
            return false;
        }

        return true;
    
protected voiddoLaunch(org.eclipse.debug.core.ILaunchConfiguration configuration, java.lang.String mode, org.eclipse.core.runtime.IProgressMonitor monitor, org.eclipse.core.resources.IProject project, AndroidLaunch androidLaunch, AndroidLaunchConfiguration config, AndroidLaunchController controller, org.eclipse.core.resources.IFile applicationPackage, com.android.ide.eclipse.common.project.AndroidManifestParser manifestParser)

        
       String activityName = null;
        
        if (config.mLaunchAction == ACTION_ACTIVITY) { 
            // Get the activity name defined in the config
            activityName = getActivityName(configuration);
    
            // Get the full activity list and make sure the one we got matches.
            Activity[] activities = manifestParser.getActivities();
    
            // first we check that there are, in fact, activities.
            if (activities.length == 0) {
                // if the activities list is null, then the manifest is empty
                // and we can't launch the app. We'll revert to a sync-only launch
                AdtPlugin.printErrorToConsole(project,
                        "The Manifest defines no activity!",
                        "The launch will only sync the application package on the device!");
                config.mLaunchAction = ACTION_DO_NOTHING;
            } else if (activityName == null) {
                // if the activity we got is null, we look for the default one.
                AdtPlugin.printErrorToConsole(project,
                        "No activity specified! Getting the launcher activity.");
                Activity launcherActivity = manifestParser.getLauncherActivity();
                if (launcherActivity != null) {
                    activityName = launcherActivity.getName();
                }

                // if there's no default activity. We revert to a sync-only launch.
                if (activityName == null) {
                    revertToNoActionLaunch(project, config);
                }
            } else {
    
                // check the one we got from the config matches any from the list
                boolean match = false;
                for (Activity a : activities) {
                    if (a != null && a.getName().equals(activityName)) {
                        match = true;
                        break;
                    }
                }
    
                // if we didn't find a match, we revert to the default activity if any.
                if (match == false) {
                    AdtPlugin.printErrorToConsole(project,
                            "The specified activity does not exist! Getting the launcher activity.");
                    Activity launcherActivity = manifestParser.getLauncherActivity();
                    if (launcherActivity != null) {
                        activityName = launcherActivity.getName();
                    }
            
                    // if there's no default activity. We revert to a sync-only launch.
                    if (activityName == null) {
                        revertToNoActionLaunch(project, config);
                    }
                }
            }
        } else if (config.mLaunchAction == ACTION_DEFAULT) {
            Activity launcherActivity = manifestParser.getLauncherActivity();
            if (launcherActivity != null) {
                activityName = launcherActivity.getName();
            }
            
            // if there's no default activity. We revert to a sync-only launch.
            if (activityName == null) {
                revertToNoActionLaunch(project, config);
            }
        }

        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.getPackage(), manifestParser.getDebuggable(),
                manifestParser.getApiLevelRequirement(), launchAction, config, androidLaunch,
                monitor);
    
private java.lang.StringgetActivityName(org.eclipse.debug.core.ILaunchConfiguration configuration)
Returns the name of the activity.

        String empty = "";
        String activityName;
        try {
            activityName = configuration.getAttribute(ATTR_ACTIVITY, empty);
        } catch (CoreException e) {
            return null;
        }

        return (activityName != empty) ? activityName : null;
    
public org.eclipse.debug.core.ILaunchgetLaunch(org.eclipse.debug.core.ILaunchConfiguration configuration, java.lang.String mode)
{@inheritDoc}

throws
CoreException

        return new AndroidLaunch(configuration, mode, null);
    
private org.eclipse.core.resources.IProjectgetProject(org.eclipse.debug.core.ILaunchConfiguration configuration)
Returns the IProject object matching the name found in the configuration object under the name IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME

param
configuration
return
The IProject object or null

        // get the project name from the config
        String projectName;
        try {
            projectName = configuration.getAttribute(
                    IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "");
        } catch (CoreException e) {
            return null;
        }

        // get the current workspace
        IWorkspace workspace = ResourcesPlugin.getWorkspace();

        // and return the project with the name from the config
        return workspace.getRoot().getProject(projectName);
    
public voidlaunch(org.eclipse.debug.core.ILaunchConfiguration configuration, java.lang.String mode, org.eclipse.debug.core.ILaunch launch, org.eclipse.core.runtime.IProgressMonitor monitor)

 //$NON-NLS-1$

         
                  
        // We need to check if it's a standard launch or if it's a launch
        // to debug an application already running.
        int debugPort = AndroidLaunchController.getPortForConfig(configuration);

        // get the project
        IProject project = getProject(configuration);

        // first we make sure the launch is of the proper type
        AndroidLaunch androidLaunch = null;
        if (launch instanceof AndroidLaunch) {
            androidLaunch = (AndroidLaunch)launch;
        } else {
            // wrong type, not sure how we got there, but we don't do
            // anything else
            AdtPlugin.printErrorToConsole(project, "Wrong Launch Type!");
            return;
        }

        // if we have a valid debug port, this means we're debugging an app
        // that's already launched.
        if (debugPort != INVALID_DEBUG_PORT) {
            AndroidLaunchController.launchRemoteDebugger(debugPort, androidLaunch, monitor);
            return;
        }

        if (project == null) {
            AdtPlugin.printErrorToConsole("Couldn't get project object!");
            androidLaunch.stopLaunch();
            return;
        }

        // check if the project has errors, and abort in this case.
        if (ProjectHelper.hasError(project, true)) {
            AdtPlugin.displayError("Android Launch",
                    "Your project contains error(s), please fix them before running your application.");
            return;
        }

        AdtPlugin.printToConsole(project, "------------------------------"); //$NON-NLS-1$
        AdtPlugin.printToConsole(project, "Android Launch!");

        // check if the project is using the proper sdk.
        // if that throws an exception, we simply let it propagate to the caller.
        if (checkAndroidProject(project) == false) {
            AdtPlugin.printErrorToConsole(project, "Project is not an Android Project. Aborting!");
            androidLaunch.stopLaunch();
            return;
        }

        // Check adb status and abort if needed.
        AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
        if (bridge == null || bridge.isConnected() == false) {
            try {
                int connections = -1;
                int restarts = -1;
                if (bridge != null) {
                    connections = bridge.getConnectionAttemptCount();
                    restarts = bridge.getRestartAttemptCount();
                }

                // if we get -1, the device monitor is not even setup (anymore?).
                // We need to ask the user to restart eclipse.
                // This shouldn't happen, but it's better to let the user know in case it does.
                if (connections == -1 || restarts == -1) {
                    AdtPlugin.printErrorToConsole(project, 
                            "The connection to adb is down, and a severe error has occured.",
                            "You must restart adb and Eclipse.",
                            String.format(
                                    "Please ensure that adb is correctly located at '%1$s' and can be executed.",
                                    AdtPlugin.getOsAbsoluteAdb()));
                    return;
                }
                
                if (restarts == 0) {
                    AdtPlugin.printErrorToConsole(project,
                            "Connection with adb was interrupted.",
                            String.format("%1$s attempts have been made to reconnect.", connections),
                            "You may want to manually restart adb from the Devices view.");
                } else {
                    AdtPlugin.printErrorToConsole(project,
                            "Connection with adb was interrupted, and attempts to reconnect have failed.",
                            String.format("%1$s attempts have been made to restart adb.", restarts),
                            "You may want to manually restart adb from the Devices view.");
                    
                }
                return;
            } finally {
                androidLaunch.stopLaunch();
            }
        }
        
        // since adb is working, we let the user know
        // TODO have a verbose mode for launch with more info (or some of the less useful info we now have).
        AdtPlugin.printToConsole(project, "adb is running normally.");

        // make a config class
        AndroidLaunchConfiguration config = new AndroidLaunchConfiguration();

        // fill it with the config coming from the ILaunchConfiguration object
        config.set(configuration);

        // get the launch controller singleton
        AndroidLaunchController controller = AndroidLaunchController.getInstance();

        // get the application package
        IFile applicationPackage = ProjectHelper.getApplicationPackage(project);
        if (applicationPackage == null) {
            androidLaunch.stopLaunch();
            return;
        }

        // we need some information from the manifest
        AndroidManifestParser manifestParser = AndroidManifestParser.parse(
                BaseProjectHelper.getJavaProject(project), null /* errorListener */,
                true /* gatherData */, false /* markErrors */);
        
        if (manifestParser == null) {
            AdtPlugin.printErrorToConsole(project, "Failed to parse AndroidManifest: aborting!");
            androidLaunch.stopLaunch();
            return;
        }

        doLaunch(configuration, mode, monitor, project, androidLaunch, config, controller,
                applicationPackage, manifestParser);
    
private final voidrevertToNoActionLaunch(org.eclipse.core.resources.IProject project, AndroidLaunchConfiguration config)

        AdtPlugin.printErrorToConsole(project,
                "No Launcher activity found!",
                "The launch will only sync the application package on the device!");
        config.mLaunchAction = ACTION_DO_NOTHING;