import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Activity;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
activityName = getActivityName(configuration);
// Get the full activity list and make sure the one we got matches.
- String[] activities = manifestParser.getActivities();
+ Activity[] activities = manifestParser.getActivities();
// first we check that there are, in fact, activities.
if (activities.length == 0) {
// if the activity we got is null, we look for the default one.
AdtPlugin.printErrorToConsole(project,
"No activity specified! Getting the launcher activity.");
- activityName = manifestParser.getLauncherActivity();
-
+ 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);
// check the one we got from the config matches any from the list
boolean match = false;
- for (String a : activities) {
- if (a != null && a.equals(activityName)) {
+ for (Activity a : activities) {
+ if (a != null && a.getName().equals(activityName)) {
match = true;
break;
}
if (match == false) {
AdtPlugin.printErrorToConsole(project,
"The specified activity does not exist! Getting the launcher activity.");
- activityName = manifestParser.getLauncherActivity();
+ 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) {
}
}
} else if (config.mLaunchAction == ACTION_DEFAULT) {
- activityName = manifestParser.getLauncherActivity();
+ 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) {
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Activity;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
+import java.util.ArrayList;
+
/**
* Class for the main launch configuration tab.
*/
private Button mProjButton;
private Combo mActivityCombo;
- private String[] mActivities;
+ private final ArrayList<Activity> mActivities = new ArrayList<Activity>();
private WidgetListener mListener = new WidgetListener();
// add the activity
int selection = mActivityCombo.getSelectionIndex();
- if (mActivities != null && selection >=0 && selection < mActivities.length) {
- configuration.setAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, mActivities[selection]);
+ if (mActivities != null && selection >=0 && selection < mActivities.size()) {
+ configuration.setAttribute(LaunchConfigDelegate.ATTR_ACTIVITY,
+ mActivities.get(selection).getName());
}
// link the project and the launch config.
mActivityCombo.setEnabled(true);
if (activityName == null || activityName.equals(EMPTY_STRING)) {
mActivityCombo.clearSelection();
- } else if (mActivities != null && mActivities.length > 0) {
+ } else if (mActivities != null && mActivities.size() > 0) {
// look for the name of the activity in the combo.
boolean found = false;
- for (int i = 0 ; i < mActivities.length ; i++) {
- if (activityName.equals(mActivities[i])) {
+ for (int i = 0 ; i < mActivities.size() ; i++) {
+ if (activityName.equals(mActivities.get(i).getName())) {
found = true;
mActivityCombo.select(i);
break;
BaseProjectHelper.getJavaProject(project), null /* errorListener */,
true /* gatherData */, false /* markErrors */);
if (manifestParser != null) {
- mActivities = manifestParser.getActivities();
-
+ Activity[] activities = manifestParser.getActivities();
+
+ mActivities.clear();
mActivityCombo.removeAll();
-
- if (mActivities.length > 0) {
+
+ for (Activity activity : activities) {
+ if (activity.getExported() && activity.hasAction()) {
+ mActivities.add(activity);
+ mActivityCombo.add(activity.getName());
+ }
+ }
+
+ if (mActivities.size() > 0) {
if (mLaunchAction == LaunchConfigDelegate.ACTION_ACTIVITY) {
mActivityCombo.setEnabled(true);
}
- for (String s : mActivities) {
- mActivityCombo.add(s);
- }
} else {
mActivityCombo.setEnabled(false);
}
// if we reach this point, either project is null, or we got an exception during
// the parsing. In either case, we empty the activity list.
mActivityCombo.removeAll();
- mActivities = null;
+ mActivities.clear();
}
/**
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
+ private final static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
private final String mName;
private final String mTargetPackage;
- public Instrumentation(String name, String targetPackage) {
+ Instrumentation(String name, String targetPackage) {
mName = name;
mTargetPackage = targetPackage;
}
}
/**
+ * Activity info obtained from the manifest.
+ */
+ public static class Activity {
+ private final String mName;
+ private final boolean mExported;
+ private boolean mHasAction = false;
+ private boolean mHasMainAction = false;
+ private boolean mHasLauncherCategory = false;
+
+ public Activity(String name, boolean exported) {
+ mName = name;
+ mExported = exported;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public boolean getExported() {
+ return mExported;
+ }
+
+ public boolean hasAction() {
+ return mHasAction;
+ }
+
+ public boolean isHomeActivity() {
+ return mHasMainAction && mHasLauncherCategory;
+ }
+
+ void setHasAction(boolean hasAction) {
+ mHasAction = hasAction;
+ }
+
+ /** If the activity doesn't yet have a filter set for the launcher, this resets both
+ * flags. This is to handle multiple intent-filters where one could have the valid
+ * action, and another one of the valid category.
+ */
+ void resetIntentFilter() {
+ if (isHomeActivity() == false) {
+ mHasMainAction = mHasLauncherCategory = false;
+ }
+ }
+
+ void setHasMainAction(boolean hasMainAction) {
+ mHasMainAction = hasMainAction;
+ }
+
+ void setHasLauncherCategory(boolean hasLauncherCategory) {
+ mHasLauncherCategory = hasLauncherCategory;
+ }
+ }
+
+ /**
* XML error & data handler used when parsing the AndroidManifest.xml file.
* <p/>
* This serves both as an {@link XmlErrorHandler} to report errors and as a data repository
/** Application package */
private String mPackage;
/** List of all activities */
- private final ArrayList<String> mActivities = new ArrayList<String>();
+ private final ArrayList<Activity> mActivities = new ArrayList<Activity>();
/** Launcher activity */
- private String mLauncherActivity = null;
+ private Activity mLauncherActivity = null;
/** list of process names declared by the manifest */
private Set<String> mProcesses = null;
/** debuggable attribute value. If null, the attribute is not present. */
private boolean mMarkErrors = false;
private int mCurrentLevel = 0;
private int mValidLevel = 0;
- private boolean mFoundMainAction = false;
- private boolean mFoundLauncherCategory = false;
- private String mCurrentActivity = null;
+ private Activity mCurrentActivity = null;
private Locator mLocator;
/**
* Returns the list of activities found in the manifest.
* @return An array of fully qualified class names, or empty if no activity were found.
*/
- String[] getActivities() {
- return mActivities.toArray(new String[mActivities.size()]);
+ Activity[] getActivities() {
+ return mActivities.toArray(new Activity[mActivities.size()]);
}
/**
* up in the HOME screen.
* @return the fully qualified name of a HOME activity or null if none were found.
*/
- String getLauncherActivity() {
+ Activity getLauncherActivity() {
return mLauncherActivity;
}
case LEVEL_INTENT_FILTER:
// only process this level if we are in an activity
if (mCurrentActivity != null && NODE_INTENT.equals(localName)) {
- // if we're at the intent level, lets reset some flag to
- // be used when parsing the children
- mFoundMainAction = false;
- mFoundLauncherCategory = false;
+ mCurrentActivity.resetIntentFilter();
mValidLevel++;
}
break;
case LEVEL_CATEGORY:
- if (mCurrentActivity != null && mLauncherActivity == null) {
+ if (mCurrentActivity != null) {
if (NODE_ACTION.equals(localName)) {
// get the name attribute
- if (ACTION_MAIN.equals(
- getAttributeValue(attributes, ATTRIBUTE_NAME,
- true /* hasNamespace */))) {
- mFoundMainAction = true;
+ String action = getAttributeValue(attributes, ATTRIBUTE_NAME,
+ true /* hasNamespace */);
+ if (action != null) {
+ mCurrentActivity.setHasAction(true);
+ mCurrentActivity.setHasMainAction(
+ ACTION_MAIN.equals(action));
}
} else if (NODE_CATEGORY.equals(localName)) {
- if (CATEGORY_LAUNCHER.equals(
- getAttributeValue(attributes, ATTRIBUTE_NAME,
- true /* hasNamespace */))) {
- mFoundLauncherCategory = true;
+ String category = getAttributeValue(attributes, ATTRIBUTE_NAME,
+ true /* hasNamespace */);
+ if (CATEGORY_LAUNCHER.equals(category)) {
+ mCurrentActivity.setHasLauncherCategory(true);
}
}
case LEVEL_INTENT_FILTER:
// if we found both a main action and a launcher category, this is our
// launcher activity!
- if (mCurrentActivity != null &&
- mFoundMainAction && mFoundLauncherCategory) {
+ if (mCurrentActivity != null && mCurrentActivity.isHomeActivity()) {
mLauncherActivity = mCurrentActivity;
}
break;
String activityName = getAttributeValue(attributes, ATTRIBUTE_NAME,
true /* hasNamespace */);
if (activityName != null) {
- mCurrentActivity = combinePackageAndClassName(mPackage, activityName);
+ activityName = combinePackageAndClassName(mPackage, activityName);
+
+ // get the exported flag.
+ String exportedStr = getAttributeValue(attributes, ATTRIBUTE_EXPORTED, true);
+ boolean exported = exportedStr == null ||
+ exportedStr.toLowerCase().equals("true"); // $NON-NLS-1$
+ mCurrentActivity = new Activity(activityName, exported);
mActivities.add(mCurrentActivity);
if (mMarkErrors) {
- checkClass(mCurrentActivity, AndroidConstants.CLASS_ACTIVITY,
+ checkClass(activityName, AndroidConstants.CLASS_ACTIVITY,
true /* testVisibility */);
}
} else {
// no activity found! Aapt will output an error,
// so we don't have to do anything
- mCurrentActivity = activityName;
+ mCurrentActivity = null;
}
String processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
private static SAXParserFactory sParserFactory;
private final String mJavaPackage;
- private final String[] mActivities;
- private final String mLauncherActivity;
+ private final Activity[] mActivities;
+ private final Activity mLauncherActivity;
private final String[] mProcesses;
private final Boolean mDebuggable;
private final int mApiLevelRequirement;
/**
* Returns the list of activities found in the manifest.
- * @return An array of fully qualified class names, or empty if no activity were found.
+ * @return An array of {@link Activity}, or empty if no activity were found.
*/
- public String[] getActivities() {
+ public Activity[] getActivities() {
return mActivities;
}
/**
* Returns the name of one activity found in the manifest, that is configured to show
* up in the HOME screen.
- * @return the fully qualified name of a HOME activity or null if none were found.
+ * @return The {@link Activity} representing a HOME activity or null if none were found.
*/
- public String getLauncherActivity() {
+ public Activity getLauncherActivity() {
return mLauncherActivity;
}
* @param instrumentations the list of instrumentations parsed from the manifest.
* @param libraries the list of libraries in use parsed from the manifest.
*/
- private AndroidManifestParser(String javaPackage, String[] activities,
- String launcherActivity, String[] processes, Boolean debuggable,
+ private AndroidManifestParser(String javaPackage, Activity[] activities,
+ Activity launcherActivity, String[] processes, Boolean debuggable,
int apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
mJavaPackage = javaPackage;
mActivities = activities;