Merge "Fix issue #5714517: App shortcuts can result in bad task intents" into ics-mr1
This commit is contained in:
committed by
Android (Google) Code Review
commit
0c0120efa2
@ -5334,6 +5334,7 @@ package android.content {
|
||||
method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
|
||||
method public T getParcelableExtra(java.lang.String);
|
||||
method public java.lang.String getScheme();
|
||||
method public android.content.Intent getSelector();
|
||||
method public java.io.Serializable getSerializableExtra(java.lang.String);
|
||||
method public short[] getShortArrayExtra(java.lang.String);
|
||||
method public short getShortExtra(java.lang.String, short);
|
||||
@ -5346,6 +5347,7 @@ package android.content {
|
||||
method public boolean hasExtra(java.lang.String);
|
||||
method public boolean hasFileDescriptors();
|
||||
method public static android.content.Intent makeMainActivity(android.content.ComponentName);
|
||||
method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
|
||||
method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
|
||||
method public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
|
||||
method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException;
|
||||
@ -5399,6 +5401,7 @@ package android.content {
|
||||
method public void setExtrasClassLoader(java.lang.ClassLoader);
|
||||
method public android.content.Intent setFlags(int);
|
||||
method public android.content.Intent setPackage(java.lang.String);
|
||||
method public void setSelector(android.content.Intent);
|
||||
method public void setSourceBounds(android.graphics.Rect);
|
||||
method public android.content.Intent setType(java.lang.String);
|
||||
method public deprecated java.lang.String toURI();
|
||||
@ -5577,6 +5580,7 @@ package android.content {
|
||||
field public static final int FILL_IN_COMPONENT = 8; // 0x8
|
||||
field public static final int FILL_IN_DATA = 2; // 0x2
|
||||
field public static final int FILL_IN_PACKAGE = 16; // 0x10
|
||||
field public static final int FILL_IN_SELECTOR = 64; // 0x40
|
||||
field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20
|
||||
field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000
|
||||
field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
|
||||
|
@ -131,6 +131,10 @@ public class Am {
|
||||
runScreenCompat();
|
||||
} else if (op.equals("display-size")) {
|
||||
runDisplaySize();
|
||||
} else if (op.equals("to-uri")) {
|
||||
runToUri(false);
|
||||
} else if (op.equals("to-intent-uri")) {
|
||||
runToUri(true);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown command: " + op);
|
||||
}
|
||||
@ -138,6 +142,7 @@ public class Am {
|
||||
|
||||
private Intent makeIntent() throws URISyntaxException {
|
||||
Intent intent = new Intent();
|
||||
Intent baseIntent = intent;
|
||||
boolean hasIntentInfo = false;
|
||||
|
||||
mDebugOption = false;
|
||||
@ -152,35 +157,39 @@ public class Am {
|
||||
while ((opt=nextOption()) != null) {
|
||||
if (opt.equals("-a")) {
|
||||
intent.setAction(nextArgRequired());
|
||||
hasIntentInfo = true;
|
||||
if (intent == baseIntent) {
|
||||
hasIntentInfo = true;
|
||||
}
|
||||
} else if (opt.equals("-d")) {
|
||||
data = Uri.parse(nextArgRequired());
|
||||
hasIntentInfo = true;
|
||||
if (intent == baseIntent) {
|
||||
hasIntentInfo = true;
|
||||
}
|
||||
} else if (opt.equals("-t")) {
|
||||
type = nextArgRequired();
|
||||
hasIntentInfo = true;
|
||||
if (intent == baseIntent) {
|
||||
hasIntentInfo = true;
|
||||
}
|
||||
} else if (opt.equals("-c")) {
|
||||
intent.addCategory(nextArgRequired());
|
||||
hasIntentInfo = true;
|
||||
if (intent == baseIntent) {
|
||||
hasIntentInfo = true;
|
||||
}
|
||||
} else if (opt.equals("-e") || opt.equals("--es")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
intent.putExtra(key, value);
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--esn")) {
|
||||
String key = nextArgRequired();
|
||||
intent.putExtra(key, (String) null);
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--ei")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
intent.putExtra(key, Integer.valueOf(value));
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--eu")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
intent.putExtra(key, Uri.parse(value));
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--eia")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
@ -190,12 +199,10 @@ public class Am {
|
||||
list[i] = Integer.valueOf(strings[i]);
|
||||
}
|
||||
intent.putExtra(key, list);
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--el")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
intent.putExtra(key, Long.valueOf(value));
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--ela")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
@ -205,18 +212,18 @@ public class Am {
|
||||
list[i] = Long.valueOf(strings[i]);
|
||||
}
|
||||
intent.putExtra(key, list);
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("--ez")) {
|
||||
String key = nextArgRequired();
|
||||
String value = nextArgRequired();
|
||||
intent.putExtra(key, Boolean.valueOf(value));
|
||||
hasIntentInfo = true;
|
||||
} else if (opt.equals("-n")) {
|
||||
String str = nextArgRequired();
|
||||
ComponentName cn = ComponentName.unflattenFromString(str);
|
||||
if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
|
||||
intent.setComponent(cn);
|
||||
hasIntentInfo = true;
|
||||
if (intent == baseIntent) {
|
||||
hasIntentInfo = true;
|
||||
}
|
||||
} else if (opt.equals("-f")) {
|
||||
String str = nextArgRequired();
|
||||
intent.setFlags(Integer.decode(str).intValue());
|
||||
@ -264,6 +271,9 @@ public class Am {
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
||||
} else if (opt.equals("--receiver-replace-pending")) {
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
|
||||
} else if (opt.equals("--selector")) {
|
||||
intent.setDataAndType(data, type);
|
||||
intent = new Intent();
|
||||
} else if (opt.equals("-D")) {
|
||||
mDebugOption = true;
|
||||
} else if (opt.equals("-W")) {
|
||||
@ -286,25 +296,42 @@ public class Am {
|
||||
}
|
||||
intent.setDataAndType(data, type);
|
||||
|
||||
final boolean hasSelector = intent != baseIntent;
|
||||
if (hasSelector) {
|
||||
// A selector was specified; fix up.
|
||||
baseIntent.setSelector(intent);
|
||||
intent = baseIntent;
|
||||
}
|
||||
|
||||
String arg = nextArg();
|
||||
if (arg != null) {
|
||||
Intent baseIntent;
|
||||
if (arg.indexOf(':') >= 0) {
|
||||
// The argument is a URI. Fully parse it, and use that result
|
||||
// to fill in any data not specified so far.
|
||||
baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
|
||||
} else if (arg.indexOf('/') >= 0) {
|
||||
// The argument is a component name. Build an Intent to launch
|
||||
// it.
|
||||
baseIntent = null;
|
||||
if (arg == null) {
|
||||
if (hasSelector) {
|
||||
// If a selector has been specified, and no arguments
|
||||
// have been supplied for the main Intent, then we can
|
||||
// assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
|
||||
// need to have a component name specified yet, the
|
||||
// selector will take care of that.
|
||||
baseIntent = new Intent(Intent.ACTION_MAIN);
|
||||
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
baseIntent.setComponent(ComponentName.unflattenFromString(arg));
|
||||
} else {
|
||||
// Assume the argument is a package name.
|
||||
baseIntent = new Intent(Intent.ACTION_MAIN);
|
||||
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
baseIntent.setPackage(arg);
|
||||
}
|
||||
} else if (arg.indexOf(':') >= 0) {
|
||||
// The argument is a URI. Fully parse it, and use that result
|
||||
// to fill in any data not specified so far.
|
||||
baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
|
||||
} else if (arg.indexOf('/') >= 0) {
|
||||
// The argument is a component name. Build an Intent to launch
|
||||
// it.
|
||||
baseIntent = new Intent(Intent.ACTION_MAIN);
|
||||
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
baseIntent.setComponent(ComponentName.unflattenFromString(arg));
|
||||
} else {
|
||||
// Assume the argument is a package name.
|
||||
baseIntent = new Intent(Intent.ACTION_MAIN);
|
||||
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
baseIntent.setPackage(arg);
|
||||
}
|
||||
if (baseIntent != null) {
|
||||
Bundle extras = intent.getExtras();
|
||||
intent.replaceExtras((Bundle)null);
|
||||
Bundle uriExtras = baseIntent.getExtras();
|
||||
@ -315,7 +342,7 @@ public class Am {
|
||||
baseIntent.removeCategory(c);
|
||||
}
|
||||
}
|
||||
intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT);
|
||||
intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
|
||||
if (extras == null) {
|
||||
extras = uriExtras;
|
||||
} else if (uriExtras != null) {
|
||||
@ -1064,6 +1091,11 @@ public class Am {
|
||||
}
|
||||
}
|
||||
|
||||
private void runToUri(boolean intentScheme) throws Exception {
|
||||
Intent intent = makeIntent();
|
||||
System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0));
|
||||
}
|
||||
|
||||
private class IntentReceiver extends IIntentReceiver.Stub {
|
||||
private boolean mFinished = false;
|
||||
|
||||
@ -1233,6 +1265,8 @@ public class Am {
|
||||
" am monitor [--gdb <port>]\n" +
|
||||
" am screen-compat [on|off] <PACKAGE>\n" +
|
||||
" am display-size [reset|MxN]\n" +
|
||||
" am to-uri [INTENT]\n" +
|
||||
" am to-intent-uri [INTENT]\n" +
|
||||
"\n" +
|
||||
"am start: start an Activity. Options are:\n" +
|
||||
" -D: enable debugging\n" +
|
||||
@ -1284,6 +1318,10 @@ public class Am {
|
||||
"\n" +
|
||||
"am display-size: override display size.\n" +
|
||||
"\n" +
|
||||
"am to-uri: print the given Intent specification as a URI.\n" +
|
||||
"\n" +
|
||||
"am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
|
||||
"\n" +
|
||||
"<INTENT> specifications include these flags and arguments:\n" +
|
||||
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
|
||||
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
|
||||
@ -1308,6 +1346,7 @@ public class Am {
|
||||
" [--activity-single-top] [--activity-clear-task]\n" +
|
||||
" [--activity-task-on-home]\n" +
|
||||
" [--receiver-registered-only] [--receiver-replace-pending]\n" +
|
||||
" [--selector]\n" +
|
||||
" [<URI> | <PACKAGE> | <COMPONENT>]\n"
|
||||
);
|
||||
}
|
||||
|
@ -2315,6 +2315,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the browser application.
|
||||
* The activity should be able to browse the Internet.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER";
|
||||
@ -2322,6 +2327,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the calculator application.
|
||||
* The activity should be able to perform standard arithmetic operations.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR";
|
||||
@ -2329,6 +2339,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the calendar application.
|
||||
* The activity should be able to view and manipulate calendar entries.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR";
|
||||
@ -2336,6 +2351,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the contacts application.
|
||||
* The activity should be able to view and manipulate address book entries.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS";
|
||||
@ -2343,6 +2363,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the email application.
|
||||
* The activity should be able to send and receive email.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL";
|
||||
@ -2351,6 +2376,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
* Used with {@link #ACTION_MAIN} to launch the gallery application.
|
||||
* The activity should be able to view and manipulate image and video files
|
||||
* stored on the device.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY";
|
||||
@ -2358,6 +2388,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the maps application.
|
||||
* The activity should be able to show the user's current location and surroundings.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS";
|
||||
@ -2365,13 +2400,24 @@ public class Intent implements Parcelable, Cloneable {
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the messaging application.
|
||||
* The activity should be able to send and receive text messages.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING";
|
||||
|
||||
/**
|
||||
* Used with {@link #ACTION_MAIN} to launch the music application.
|
||||
* The activity should be able to play, browse, or manipulate music files stored on the device.
|
||||
* The activity should be able to play, browse, or manipulate music files
|
||||
* stored on the device.
|
||||
* <p>NOTE: This should not be used as the primary key of an Intent,
|
||||
* since it will not result in the app launching with the correct
|
||||
* action and category. Instead, use this with
|
||||
* {@link #makeMainSelectorActivity(String, String) to generate a main
|
||||
* Intent with this category in the selector.</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
|
||||
public static final String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC";
|
||||
@ -2963,6 +3009,7 @@ public class Intent implements Parcelable, Cloneable {
|
||||
private HashSet<String> mCategories;
|
||||
private Bundle mExtras;
|
||||
private Rect mSourceBounds;
|
||||
private Intent mSelector;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -2991,6 +3038,9 @@ public class Intent implements Parcelable, Cloneable {
|
||||
if (o.mSourceBounds != null) {
|
||||
this.mSourceBounds = new Rect(o.mSourceBounds);
|
||||
}
|
||||
if (o.mSelector != null) {
|
||||
this.mSelector = new Intent(o.mSelector);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -3130,6 +3180,39 @@ public class Intent implements Parcelable, Cloneable {
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an Intent for the main activity of an application, without
|
||||
* specifying a specific activity to run but giving a selector to find
|
||||
* the activity. This results in a final Intent that is structured
|
||||
* the same as when the application is launched from
|
||||
* Home. For anything else that wants to launch an application in the
|
||||
* same way, it is important that they use an Intent structured the same
|
||||
* way, and can use this function to ensure this is the case.
|
||||
*
|
||||
* <p>The returned Intent has {@link #ACTION_MAIN} as its action, and includes the
|
||||
* category {@link #CATEGORY_LAUNCHER}. This does <em>not</em> have
|
||||
* {@link #FLAG_ACTIVITY_NEW_TASK} set, though typically you will want
|
||||
* to do that through {@link #addFlags(int)} on the returned Intent.
|
||||
*
|
||||
* @param selectorAction The action name of the Intent's selector.
|
||||
* @param selectorCategory The name of a category to add to the Intent's
|
||||
* selector.
|
||||
* @return Returns a newly created Intent that can be used to launch the
|
||||
* activity as a main application entry.
|
||||
*
|
||||
* @see #setSelector(Intent)
|
||||
*/
|
||||
public static Intent makeMainSelectorActivity(String selectorAction,
|
||||
String selectorCategory) {
|
||||
Intent intent = new Intent(ACTION_MAIN);
|
||||
intent.addCategory(CATEGORY_LAUNCHER);
|
||||
Intent selector = new Intent();
|
||||
selector.setAction(selectorAction);
|
||||
selector.addCategory(selectorCategory);
|
||||
intent.setSelector(selector);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an Intent that can be used to re-launch an application's task
|
||||
* in its base state. This is like {@link #makeMainActivity(ComponentName)},
|
||||
@ -3205,6 +3288,7 @@ public class Intent implements Parcelable, Cloneable {
|
||||
|
||||
// new format
|
||||
Intent intent = new Intent(ACTION_VIEW);
|
||||
Intent baseIntent = intent;
|
||||
|
||||
// fetch data part, if present
|
||||
String data = i >= 0 ? uri.substring(0, i) : null;
|
||||
@ -3214,8 +3298,9 @@ public class Intent implements Parcelable, Cloneable {
|
||||
// loop over contents of Intent, all name=value;
|
||||
while (!uri.startsWith("end", i)) {
|
||||
int eq = uri.indexOf('=', i);
|
||||
int semi = uri.indexOf(';', eq);
|
||||
String value = Uri.decode(uri.substring(eq + 1, semi));
|
||||
if (eq < 0) eq = i-1;
|
||||
int semi = uri.indexOf(';', i);
|
||||
String value = eq < semi ? Uri.decode(uri.substring(eq + 1, semi)) : "";
|
||||
|
||||
// action
|
||||
if (uri.startsWith("action=", i)) {
|
||||
@ -3257,6 +3342,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
intent.mSourceBounds = Rect.unflattenFromString(value);
|
||||
}
|
||||
|
||||
// selector
|
||||
else if (semi == (i+3) && uri.startsWith("SEL", i)) {
|
||||
intent = new Intent();
|
||||
}
|
||||
|
||||
// extra
|
||||
else {
|
||||
String key = Uri.decode(uri.substring(i + 2, eq));
|
||||
@ -3280,6 +3370,12 @@ public class Intent implements Parcelable, Cloneable {
|
||||
i = semi + 1;
|
||||
}
|
||||
|
||||
if (intent != baseIntent) {
|
||||
// The Intent had a selector; fix it up.
|
||||
baseIntent.setSelector(intent);
|
||||
intent = baseIntent;
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
if (data.startsWith("intent:")) {
|
||||
data = data.substring(7);
|
||||
@ -3605,7 +3701,7 @@ public class Intent implements Parcelable, Cloneable {
|
||||
* Return the set of all categories in the intent. If there are no categories,
|
||||
* returns NULL.
|
||||
*
|
||||
* @return Set The set of categories you can examine. Do not modify!
|
||||
* @return The set of categories you can examine. Do not modify!
|
||||
*
|
||||
* @see #hasCategory
|
||||
* @see #addCategory
|
||||
@ -3614,6 +3710,16 @@ public class Intent implements Parcelable, Cloneable {
|
||||
return mCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specific selector associated with this Intent. If there is
|
||||
* none, returns null. See {@link #setSelector} for more information.
|
||||
*
|
||||
* @see #setSelector
|
||||
*/
|
||||
public Intent getSelector() {
|
||||
return mSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ClassLoader that will be used when unmarshalling
|
||||
* any Parcelable values from the extras of this Intent.
|
||||
@ -4432,6 +4538,49 @@ public class Intent implements Parcelable, Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a selector for this Intent. This is a modification to the kinds of
|
||||
* things the Intent will match. If the selector is set, it will be used
|
||||
* when trying to find entities that can handle the Intent, instead of the
|
||||
* main contents of the Intent. This allows you build an Intent containing
|
||||
* a generic protocol while targeting it more specifically.
|
||||
*
|
||||
* <p>An example of where this may be used is with things like
|
||||
* {@link #CATEGORY_APP_BROWSER}. This category allows you to build an
|
||||
* Intent that will launch the Browser application. However, the correct
|
||||
* main entry point of an application is actually {@link #ACTION_MAIN}
|
||||
* {@link #CATEGORY_LAUNCHER} with {@link #setComponent(ComponentName)}
|
||||
* used to specify the actual Activity to launch. If you launch the browser
|
||||
* with something different, undesired behavior may happen if the user has
|
||||
* previously or later launches it the normal way, since they do not match.
|
||||
* Instead, you can build an Intent with the MAIN action (but no ComponentName
|
||||
* yet specified) and set a selector with {@link #ACTION_MAIN} and
|
||||
* {@link #CATEGORY_APP_BROWSER} to point it specifically to the browser activity.
|
||||
*
|
||||
* <p>Setting a selector does not impact the behavior of
|
||||
* {@link #filterEquals(Intent)} and {@link #filterHashCode()}. This is part of the
|
||||
* desired behavior of a selector -- it does not impact the base meaning
|
||||
* of the Intent, just what kinds of things will be matched against it
|
||||
* when determining who can handle it.</p>
|
||||
*
|
||||
* <p>You can not use both a selector and {@link #setPackage(String)} on
|
||||
* the same base Intent.</p>
|
||||
*
|
||||
* @param selector The desired selector Intent; set to null to not use
|
||||
* a special selector.
|
||||
*/
|
||||
public void setSelector(Intent selector) {
|
||||
if (selector == this) {
|
||||
throw new IllegalArgumentException(
|
||||
"Intent being set as a selector of itself");
|
||||
}
|
||||
if (selector != null && mPackage != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't set selector when package name is already set");
|
||||
}
|
||||
mSelector = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended data to the intent. The name must include a package
|
||||
* prefix, for example the app com.android.contacts would use names
|
||||
@ -5259,6 +5408,10 @@ public class Intent implements Parcelable, Cloneable {
|
||||
* @see #resolveActivity
|
||||
*/
|
||||
public Intent setPackage(String packageName) {
|
||||
if (packageName != null && mSelector != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't set package name when selector is already set");
|
||||
}
|
||||
mPackage = packageName;
|
||||
return this;
|
||||
}
|
||||
@ -5394,11 +5547,17 @@ public class Intent implements Parcelable, Cloneable {
|
||||
public static final int FILL_IN_PACKAGE = 1<<4;
|
||||
|
||||
/**
|
||||
* Use with {@link #fillIn} to allow the current package value to be
|
||||
* Use with {@link #fillIn} to allow the current bounds rectangle to be
|
||||
* overwritten, even if it is already set.
|
||||
*/
|
||||
public static final int FILL_IN_SOURCE_BOUNDS = 1<<5;
|
||||
|
||||
/**
|
||||
* Use with {@link #fillIn} to allow the current selector to be
|
||||
* overwritten, even if it is already set.
|
||||
*/
|
||||
public static final int FILL_IN_SELECTOR = 1<<6;
|
||||
|
||||
/**
|
||||
* Copy the contents of <var>other</var> in to this object, but only
|
||||
* where fields are not defined by this object. For purposes of a field
|
||||
@ -5419,11 +5578,13 @@ public class Intent implements Parcelable, Cloneable {
|
||||
*
|
||||
* <p>In addition, you can use the {@link #FILL_IN_ACTION},
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
|
||||
* and {@link #FILL_IN_COMPONENT} to override the restriction where the
|
||||
* {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and
|
||||
* {@link #FILL_IN_SELECTOR} to override the restriction where the
|
||||
* corresponding field will not be replaced if it is already set.
|
||||
*
|
||||
* <p>Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} is explicitly
|
||||
* specified.
|
||||
* specified. The selector will only be copied if {@link #FILL_IN_SELECTOR} is
|
||||
* explicitly specified.
|
||||
*
|
||||
* <p>For example, consider Intent A with {data="foo", categories="bar"}
|
||||
* and Intent B with {action="gotit", data-type="some/thing",
|
||||
@ -5439,7 +5600,8 @@ public class Intent implements Parcelable, Cloneable {
|
||||
*
|
||||
* @return Returns a bit mask of {@link #FILL_IN_ACTION},
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
|
||||
* and {@link #FILL_IN_COMPONENT} indicating which fields were changed.
|
||||
* {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and
|
||||
* {@link #FILL_IN_SELECTOR} indicating which fields were changed.
|
||||
*/
|
||||
public int fillIn(Intent other, int flags) {
|
||||
int changes = 0;
|
||||
@ -5464,8 +5626,20 @@ public class Intent implements Parcelable, Cloneable {
|
||||
}
|
||||
if (other.mPackage != null
|
||||
&& (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) {
|
||||
mPackage = other.mPackage;
|
||||
changes |= FILL_IN_PACKAGE;
|
||||
// Only do this if mSelector is not set.
|
||||
if (mSelector == null) {
|
||||
mPackage = other.mPackage;
|
||||
changes |= FILL_IN_PACKAGE;
|
||||
}
|
||||
}
|
||||
// Selector is special: it can only be set if explicitly allowed,
|
||||
// for the same reason as the component name.
|
||||
if (other.mSelector != null && (flags&FILL_IN_SELECTOR) != 0) {
|
||||
if (mPackage == null) {
|
||||
mSelector = new Intent(other.mSelector);
|
||||
mPackage = null;
|
||||
changes |= FILL_IN_SELECTOR;
|
||||
}
|
||||
}
|
||||
// Component is special: it can -only- be set if explicitly allowed,
|
||||
// since otherwise the sender could force the intent somewhere the
|
||||
@ -5763,6 +5937,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
first = false;
|
||||
b.append("(has extras)");
|
||||
}
|
||||
if (mSelector != null) {
|
||||
b.append(" sel={");
|
||||
mSelector.toShortString(b, secure, comp, extras);
|
||||
b.append("}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5823,6 +6002,21 @@ public class Intent implements Parcelable, Cloneable {
|
||||
|
||||
uri.append("#Intent;");
|
||||
|
||||
toUriInner(uri, scheme, flags);
|
||||
if (mSelector != null) {
|
||||
uri.append("SEL;");
|
||||
// Note that for now we are not going to try to handle the
|
||||
// data part; not clear how to represent this as a URI, and
|
||||
// not much utility in it.
|
||||
mSelector.toUriInner(uri, null, flags);
|
||||
}
|
||||
|
||||
uri.append("end");
|
||||
|
||||
return uri.toString();
|
||||
}
|
||||
|
||||
private void toUriInner(StringBuilder uri, String scheme, int flags) {
|
||||
if (scheme != null) {
|
||||
uri.append("scheme=").append(scheme).append(';');
|
||||
}
|
||||
@ -5877,10 +6071,6 @@ public class Intent implements Parcelable, Cloneable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uri.append("end");
|
||||
|
||||
return uri.toString();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
@ -5911,6 +6101,13 @@ public class Intent implements Parcelable, Cloneable {
|
||||
out.writeInt(0);
|
||||
}
|
||||
|
||||
if (mSelector != null) {
|
||||
out.writeInt(1);
|
||||
mSelector.writeToParcel(out, flags);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
|
||||
out.writeBundle(mExtras);
|
||||
}
|
||||
|
||||
@ -5952,6 +6149,10 @@ public class Intent implements Parcelable, Cloneable {
|
||||
mCategories = null;
|
||||
}
|
||||
|
||||
if (in.readInt() != 0) {
|
||||
mSelector = new Intent(in);
|
||||
}
|
||||
|
||||
mExtras = in.readBundle();
|
||||
}
|
||||
|
||||
|
@ -1151,8 +1151,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
intent.setComponent(cn);
|
||||
title = info.loadLabel(packageManager).toString();
|
||||
} else if (category != null) {
|
||||
intent = new Intent(Intent.ACTION_MAIN, null);
|
||||
intent.addCategory(category);
|
||||
intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
|
||||
title = "";
|
||||
} else {
|
||||
Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr
|
||||
|
@ -1638,8 +1638,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
if (down && repeatCount == 0) {
|
||||
String category = sApplicationLaunchKeyCategories.get(keyCode);
|
||||
if (category != null) {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addCategory(category);
|
||||
Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
mContext.startActivity(intent);
|
||||
|
@ -54,8 +54,17 @@ class TaskRecord extends ThumbnailHolder {
|
||||
|
||||
void setIntent(Intent _intent, ActivityInfo info) {
|
||||
stringName = null;
|
||||
|
||||
|
||||
if (info.targetActivity == null) {
|
||||
if (_intent != null) {
|
||||
// If this Intent has a selector, we want to clear it for the
|
||||
// recent task since it is not relevant if the user later wants
|
||||
// to re-launch the app.
|
||||
if (_intent.getSelector() != null) {
|
||||
_intent = new Intent(_intent);
|
||||
_intent.setSelector(null);
|
||||
}
|
||||
}
|
||||
intent = _intent;
|
||||
realActivity = _intent != null ? _intent.getComponent() : null;
|
||||
origActivity = null;
|
||||
@ -65,6 +74,7 @@ class TaskRecord extends ThumbnailHolder {
|
||||
if (_intent != null) {
|
||||
Intent targetIntent = new Intent(_intent);
|
||||
targetIntent.setComponent(targetComponent);
|
||||
targetIntent.setSelector(null);
|
||||
intent = targetIntent;
|
||||
realActivity = targetComponent;
|
||||
origActivity = _intent.getComponent();
|
||||
|
@ -2162,6 +2162,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
int flags, List<ResolveInfo> query, int priority) {
|
||||
// writer
|
||||
synchronized (mPackages) {
|
||||
if (intent.getSelector() != null) {
|
||||
intent = intent.getSelector();
|
||||
}
|
||||
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
|
||||
List<PreferredActivity> prefs =
|
||||
mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
|
||||
@ -2242,7 +2245,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent,
|
||||
String resolvedType, int flags) {
|
||||
final ComponentName comp = intent.getComponent();
|
||||
ComponentName comp = intent.getComponent();
|
||||
if (comp == null) {
|
||||
if (intent.getSelector() != null) {
|
||||
intent = intent.getSelector();
|
||||
comp = intent.getComponent();
|
||||
}
|
||||
}
|
||||
if (comp != null) {
|
||||
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
|
||||
final ActivityInfo ai = getActivityInfo(comp, flags);
|
||||
@ -2440,6 +2449,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
|
||||
ComponentName comp = intent.getComponent();
|
||||
if (comp == null) {
|
||||
if (intent.getSelector() != null) {
|
||||
intent = intent.getSelector();
|
||||
comp = intent.getComponent();
|
||||
}
|
||||
}
|
||||
if (comp != null) {
|
||||
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
|
||||
ActivityInfo ai = getReceiverInfo(comp, flags);
|
||||
@ -2478,7 +2493,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
|
||||
final ComponentName comp = intent.getComponent();
|
||||
ComponentName comp = intent.getComponent();
|
||||
if (comp == null) {
|
||||
if (intent.getSelector() != null) {
|
||||
intent = intent.getSelector();
|
||||
comp = intent.getComponent();
|
||||
}
|
||||
}
|
||||
if (comp != null) {
|
||||
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
|
||||
final ServiceInfo si = getServiceInfo(comp, flags);
|
||||
|
Reference in New Issue
Block a user