Extend Intent/Uri conversion for use by Browser
This introduces a new Uri form of Intent with an "intent:" scheme, and a corresponding update to the parser to handle these, so that the browser can use this generic facility for starting activities based on the links that are clicked and allow for web pages to link to arbitrary intents. There is also a new "package" field on Intent which allows you to limit the components it finds to a given package. This replaces the new method that was added to PackageManger for doing this when resolving activities, and implements it for all Intent queries against the package manager.
This commit is contained in:
112
api/current.xml
112
api/current.xml
@ -30186,7 +30186,7 @@
|
||||
synchronized="false"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="uri" type="java.lang.String">
|
||||
@ -30237,6 +30237,17 @@
|
||||
<parameter name="defaultValue" type="long">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getPackage"
|
||||
return="java.lang.String"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getParcelableArrayExtra"
|
||||
return="android.os.Parcelable[]"
|
||||
abstract="false"
|
||||
@ -30436,6 +30447,23 @@
|
||||
<exception name="XmlPullParserException" type="org.xmlpull.v1.XmlPullParserException">
|
||||
</exception>
|
||||
</method>
|
||||
<method name="parseUri"
|
||||
return="android.content.Intent"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="uri" type="java.lang.String">
|
||||
</parameter>
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
<exception name="URISyntaxException" type="java.net.URISyntaxException">
|
||||
</exception>
|
||||
</method>
|
||||
<method name="putExtra"
|
||||
return="android.content.Intent"
|
||||
abstract="false"
|
||||
@ -31109,6 +31137,19 @@
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setPackage"
|
||||
return="android.content.Intent"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="packageName" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setType"
|
||||
return="android.content.Intent"
|
||||
abstract="false"
|
||||
@ -31123,6 +31164,17 @@
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="toURI"
|
||||
return="java.lang.String"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="toUri"
|
||||
return="java.lang.String"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -31132,6 +31184,8 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="writeToParcel"
|
||||
return="void"
|
||||
@ -32500,6 +32554,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FILL_IN_PACKAGE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="FLAG_ACTIVITY_BROUGHT_TO_FRONT"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -32709,6 +32774,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="URI_INTENT_SCHEME"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<class name="Intent.FilterComparison"
|
||||
extends="java.lang.Object"
|
||||
@ -36910,23 +36986,6 @@
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="resolveActivity"
|
||||
return="android.content.pm.ResolveInfo"
|
||||
abstract="true"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="intent" type="android.content.Intent">
|
||||
</parameter>
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
<parameter name="packageName" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="resolveContentProvider"
|
||||
return="android.content.pm.ProviderInfo"
|
||||
abstract="true"
|
||||
@ -115702,23 +115761,6 @@
|
||||
</parameter>
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
<parameter name="packageName" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="resolveActivity"
|
||||
return="android.content.pm.ResolveInfo"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="intent" type="android.content.Intent">
|
||||
</parameter>
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="resolveContentProvider"
|
||||
return="android.content.pm.ProviderInfo"
|
||||
|
@ -1519,14 +1519,16 @@ class ApplicationContext extends Context {
|
||||
// overall package (such as if it has multiple launcher entries).
|
||||
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
|
||||
intentToResolve.addCategory(Intent.CATEGORY_INFO);
|
||||
ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0, packageName);
|
||||
intentToResolve.setPackage(packageName);
|
||||
ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
|
||||
|
||||
// Otherwise, try to find a main launcher activity.
|
||||
if (resolveInfo == null) {
|
||||
// reuse the intent instance
|
||||
intentToResolve.removeCategory(Intent.CATEGORY_INFO);
|
||||
intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
resolveInfo = resolveActivity(intentToResolve, 0, packageName);
|
||||
intentToResolve.setPackage(packageName);
|
||||
resolveInfo = resolveActivity(intentToResolve, 0);
|
||||
}
|
||||
if (resolveInfo == null) {
|
||||
return null;
|
||||
@ -1773,19 +1775,6 @@ class ApplicationContext extends Context {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) {
|
||||
try {
|
||||
return mPM.resolveIntentForPackage(
|
||||
intent,
|
||||
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
|
||||
flags,
|
||||
packageName);
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException("Package manager has died", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent,
|
||||
int flags) {
|
||||
|
@ -2039,11 +2039,26 @@ public class Intent implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
// toUri() and parseUri() options.
|
||||
|
||||
/**
|
||||
* Flag for use with {@link #toUri} and {@link #parseUri}: the URI string
|
||||
* always has the "intent:" scheme. This syntax can be used when you want
|
||||
* to later disambiguate between URIs that are intended to describe an
|
||||
* Intent vs. all others that should be treated as raw URIs. When used
|
||||
* with {@link #parseUri}, any other scheme will result in a generic
|
||||
* VIEW action for that raw URI.
|
||||
*/
|
||||
public static final int URI_INTENT_SCHEME = 1<<0;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
private String mAction;
|
||||
private Uri mData;
|
||||
private String mType;
|
||||
private String mPackage;
|
||||
private ComponentName mComponent;
|
||||
private int mFlags;
|
||||
private HashSet<String> mCategories;
|
||||
@ -2064,6 +2079,7 @@ public class Intent implements Parcelable {
|
||||
this.mAction = o.mAction;
|
||||
this.mData = o.mData;
|
||||
this.mType = o.mType;
|
||||
this.mPackage = o.mPackage;
|
||||
this.mComponent = o.mComponent;
|
||||
this.mFlags = o.mFlags;
|
||||
if (o.mCategories != null) {
|
||||
@ -2083,6 +2099,7 @@ public class Intent implements Parcelable {
|
||||
this.mAction = o.mAction;
|
||||
this.mData = o.mData;
|
||||
this.mType = o.mType;
|
||||
this.mPackage = o.mPackage;
|
||||
this.mComponent = o.mComponent;
|
||||
if (o.mCategories != null) {
|
||||
this.mCategories = new HashSet<String>(o.mCategories);
|
||||
@ -2182,24 +2199,51 @@ public class Intent implements Parcelable {
|
||||
mComponent = new ComponentName(packageContext, cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #parseUri} with 0 flags.
|
||||
* @deprecated Use {@link #parseUri} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static Intent getIntent(String uri) throws URISyntaxException {
|
||||
return parseUri(uri, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an intent from a URI. This URI may encode the action,
|
||||
* category, and other intent fields, if it was returned by toURI(). If
|
||||
* the Intent was not generate by toURI(), its data will be the entire URI
|
||||
* and its action will be ACTION_VIEW.
|
||||
* category, and other intent fields, if it was returned by
|
||||
* {@link #toUri}.. If the Intent was not generate by toUri(), its data
|
||||
* will be the entire URI and its action will be ACTION_VIEW.
|
||||
*
|
||||
* <p>The URI given here must not be relative -- that is, it must include
|
||||
* the scheme and full path.
|
||||
*
|
||||
* @param uri The URI to turn into an Intent.
|
||||
* @param flags Additional processing flags. Either 0 or
|
||||
*
|
||||
* @return Intent The newly created Intent object.
|
||||
*
|
||||
* @see #toURI
|
||||
* @throws URISyntaxException Throws URISyntaxError if the basic URI syntax
|
||||
* it bad (as parsed by the Uri class) or the Intent data within the
|
||||
* URI is invalid.
|
||||
*
|
||||
* @see #toUri
|
||||
*/
|
||||
public static Intent getIntent(String uri) throws URISyntaxException {
|
||||
public static Intent parseUri(String uri, int flags) throws URISyntaxException {
|
||||
int i = 0;
|
||||
try {
|
||||
// Validate intent scheme for if requested.
|
||||
if ((flags&URI_INTENT_SCHEME) != 0) {
|
||||
if (!uri.startsWith("intent:")) {
|
||||
Intent intent = new Intent(ACTION_VIEW);
|
||||
try {
|
||||
intent.setData(Uri.parse(uri));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new URISyntaxException(uri, e.getMessage());
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
// simple case
|
||||
i = uri.lastIndexOf("#");
|
||||
if (i == -1) return new Intent(ACTION_VIEW, Uri.parse(uri));
|
||||
@ -2211,16 +2255,15 @@ public class Intent implements Parcelable {
|
||||
Intent intent = new Intent(ACTION_VIEW);
|
||||
|
||||
// fetch data part, if present
|
||||
if (i > 0) {
|
||||
intent.mData = Uri.parse(uri.substring(0, i));
|
||||
}
|
||||
String data = i >= 0 ? uri.substring(0, i) : null;
|
||||
String scheme = null;
|
||||
i += "#Intent;".length();
|
||||
|
||||
// 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.substring(eq + 1, semi);
|
||||
String value = Uri.decode(uri.substring(eq + 1, semi));
|
||||
|
||||
// action
|
||||
if (uri.startsWith("action=", i)) {
|
||||
@ -2242,15 +2285,24 @@ public class Intent implements Parcelable {
|
||||
intent.mFlags = Integer.decode(value).intValue();
|
||||
}
|
||||
|
||||
// package
|
||||
else if (uri.startsWith("package=", i)) {
|
||||
intent.mPackage = value;
|
||||
}
|
||||
|
||||
// component
|
||||
else if (uri.startsWith("component=", i)) {
|
||||
intent.mComponent = ComponentName.unflattenFromString(value);
|
||||
}
|
||||
|
||||
// scheme
|
||||
else if (uri.startsWith("scheme=", i)) {
|
||||
scheme = value;
|
||||
}
|
||||
|
||||
// extra
|
||||
else {
|
||||
String key = Uri.decode(uri.substring(i + 2, eq));
|
||||
value = Uri.decode(value);
|
||||
// create Bundle if it doesn't already exist
|
||||
if (intent.mExtras == null) intent.mExtras = new Bundle();
|
||||
Bundle b = intent.mExtras;
|
||||
@ -2271,6 +2323,23 @@ public class Intent implements Parcelable {
|
||||
i = semi + 1;
|
||||
}
|
||||
|
||||
if (data != null) {
|
||||
if (data.startsWith("intent:")) {
|
||||
data = data.substring(7);
|
||||
if (scheme != null) {
|
||||
data = scheme + ':' + data;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.length() > 0) {
|
||||
try {
|
||||
intent.mData = Uri.parse(data);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new URISyntaxException(uri, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return intent;
|
||||
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
@ -3083,6 +3152,20 @@ public class Intent implements Parcelable {
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the application package name this Intent is limited to. When
|
||||
* resolving an Intent, if non-null this limits the resolution to only
|
||||
* components in the given application package.
|
||||
*
|
||||
* @return The name of the application package for the Intent.
|
||||
*
|
||||
* @see #resolveActivity
|
||||
* @see #setPackage
|
||||
*/
|
||||
public String getPackage() {
|
||||
return mPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the concrete component associated with the intent. When receiving
|
||||
* an intent, this is the component that was found to best handle it (that is,
|
||||
@ -3118,6 +3201,9 @@ public class Intent implements Parcelable {
|
||||
* <p>If {@link #addCategory} has added any categories, the activity must
|
||||
* handle ALL of the categories specified.
|
||||
*
|
||||
* <p>If {@link #getPackage} is non-NULL, only activity components in
|
||||
* that application package will be considered.
|
||||
*
|
||||
* <p>If there are no activities that satisfy all of these conditions, a
|
||||
* null string is returned.
|
||||
*
|
||||
@ -4088,6 +4174,27 @@ public class Intent implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Usually optional) Set an explicit application package name that limits
|
||||
* the components this Intent will resolve to. If left to the default
|
||||
* value of null, all components in all applications will considered.
|
||||
* If non-null, the Intent can only match the components in the given
|
||||
* application package.
|
||||
*
|
||||
* @param packageName The name of the application package to handle the
|
||||
* intent, or null to allow any application package.
|
||||
*
|
||||
* @return Returns the same Intent object, for chaining multiple calls
|
||||
* into a single statement.
|
||||
*
|
||||
* @see #getPackage
|
||||
* @see #resolveActivity
|
||||
*/
|
||||
public Intent setPackage(String packageName) {
|
||||
mPackage = packageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Usually optional) Explicitly set the component to handle the intent.
|
||||
* If left with the default value of null, the system will determine the
|
||||
@ -4199,6 +4306,12 @@ public class Intent implements Parcelable {
|
||||
*/
|
||||
public static final int FILL_IN_COMPONENT = 1<<3;
|
||||
|
||||
/**
|
||||
* Use with {@link #fillIn} to allow the current package value to be
|
||||
* overwritten, even if it is already set.
|
||||
*/
|
||||
public static final int FILL_IN_PACKAGE = 1<<4;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -4210,14 +4323,15 @@ public class Intent implements Parcelable {
|
||||
* <li> data URI and MIME type, as set by {@link #setData(Uri)},
|
||||
* {@link #setType(String)}, or {@link #setDataAndType(Uri, String)}.
|
||||
* <li> categories, as set by {@link #addCategory}.
|
||||
* <li> package, as set by {@link #setPackage}.
|
||||
* <li> component, as set by {@link #setComponent(ComponentName)} or
|
||||
* related methods.
|
||||
* <li> each top-level name in the associated extras.
|
||||
* </ul>
|
||||
*
|
||||
* <p>In addition, you can use the {@link #FILL_IN_ACTION},
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
|
||||
* {@link #FILL_IN_COMPONENT} to override the restriction where the
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
|
||||
* and {@link #FILL_IN_COMPONENT} to override the restriction where the
|
||||
* corresponding field will not be replaced if it is already set.
|
||||
*
|
||||
* <p>For example, consider Intent A with {data="foo", categories="bar"}
|
||||
@ -4233,32 +4347,39 @@ public class Intent implements Parcelable {
|
||||
* @param flags Options to control which fields can be filled in.
|
||||
*
|
||||
* @return Returns a bit mask of {@link #FILL_IN_ACTION},
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
|
||||
* {@link #FILL_IN_COMPONENT} indicating which fields were changed.
|
||||
* {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
|
||||
* and {@link #FILL_IN_COMPONENT} indicating which fields were changed.
|
||||
*/
|
||||
public int fillIn(Intent other, int flags) {
|
||||
int changes = 0;
|
||||
if ((mAction == null && other.mAction == null)
|
||||
|| (flags&FILL_IN_ACTION) != 0) {
|
||||
if (other.mAction != null
|
||||
&& (mAction == null || (flags&FILL_IN_ACTION) != 0)) {
|
||||
mAction = other.mAction;
|
||||
changes |= FILL_IN_ACTION;
|
||||
}
|
||||
if ((mData == null && mType == null &&
|
||||
(other.mData != null || other.mType != null))
|
||||
|| (flags&FILL_IN_DATA) != 0) {
|
||||
if ((other.mData != null || other.mType != null)
|
||||
&& ((mData == null && mType == null)
|
||||
|| (flags&FILL_IN_DATA) != 0)) {
|
||||
mData = other.mData;
|
||||
mType = other.mType;
|
||||
changes |= FILL_IN_DATA;
|
||||
}
|
||||
if ((mCategories == null && other.mCategories == null)
|
||||
|| (flags&FILL_IN_CATEGORIES) != 0) {
|
||||
if (other.mCategories != null
|
||||
&& (mCategories == null || (flags&FILL_IN_CATEGORIES) != 0)) {
|
||||
if (other.mCategories != null) {
|
||||
mCategories = new HashSet<String>(other.mCategories);
|
||||
}
|
||||
changes |= FILL_IN_CATEGORIES;
|
||||
}
|
||||
if ((mComponent == null && other.mComponent == null)
|
||||
|| (flags&FILL_IN_COMPONENT) != 0) {
|
||||
if (other.mPackage != null
|
||||
&& (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) {
|
||||
mPackage = other.mPackage;
|
||||
changes |= FILL_IN_PACKAGE;
|
||||
}
|
||||
// Component is special: it can -only- be set if explicitly allowed,
|
||||
// since otherwise the sender could force the intent somewhere the
|
||||
// originator didn't intend.
|
||||
if (other.mComponent != null && (flags&FILL_IN_COMPONENT) != 0) {
|
||||
mComponent = other.mComponent;
|
||||
changes |= FILL_IN_COMPONENT;
|
||||
}
|
||||
@ -4373,6 +4494,17 @@ public class Intent implements Parcelable {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPackage != other.mPackage) {
|
||||
if (mPackage != null) {
|
||||
if (!mPackage.equals(other.mPackage)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!other.mPackage.equals(mPackage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mComponent != other.mComponent) {
|
||||
if (mComponent != null) {
|
||||
if (!mComponent.equals(other.mComponent)) {
|
||||
@ -4418,6 +4550,9 @@ public class Intent implements Parcelable {
|
||||
if (mType != null) {
|
||||
code += mType.hashCode();
|
||||
}
|
||||
if (mPackage != null) {
|
||||
code += mPackage.hashCode();
|
||||
}
|
||||
if (mComponent != null) {
|
||||
code += mComponent.hashCode();
|
||||
}
|
||||
@ -4488,6 +4623,13 @@ public class Intent implements Parcelable {
|
||||
first = false;
|
||||
b.append("flg=0x").append(Integer.toHexString(mFlags));
|
||||
}
|
||||
if (mPackage != null) {
|
||||
if (!first) {
|
||||
b.append(' ');
|
||||
}
|
||||
first = false;
|
||||
b.append("pkg=").append(mPackage);
|
||||
}
|
||||
if (comp && mComponent != null) {
|
||||
if (!first) {
|
||||
b.append(' ');
|
||||
@ -4504,28 +4646,87 @@ public class Intent implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call {@link #toUri} with 0 flags.
|
||||
* @deprecated Use {@link #toUri} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public String toURI() {
|
||||
return toUri(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this Intent into a String holding a URI representation of it.
|
||||
* The returned URI string has been properly URI encoded, so it can be
|
||||
* used with {@link Uri#parse Uri.parse(String)}. The URI contains the
|
||||
* Intent's data as the base URI, with an additional fragment describing
|
||||
* the action, categories, type, flags, package, component, and extras.
|
||||
*
|
||||
* <p>You can convert the returned string back to an Intent with
|
||||
* {@link #getIntent}.
|
||||
*
|
||||
* @param flags Additional operating flags. Either 0 or
|
||||
* {@link #URI_INTENT_SCHEME}.
|
||||
*
|
||||
* @return Returns a URI encoding URI string describing the entire contents
|
||||
* of the Intent.
|
||||
*/
|
||||
public String toUri(int flags) {
|
||||
StringBuilder uri = new StringBuilder(128);
|
||||
if (mData != null) uri.append(mData.toString());
|
||||
String scheme = null;
|
||||
if (mData != null) {
|
||||
String data = mData.toString();
|
||||
if ((flags&URI_INTENT_SCHEME) != 0) {
|
||||
final int N = data.length();
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = data.charAt(i);
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||
|| c == '.' || c == '-') {
|
||||
continue;
|
||||
}
|
||||
if (c == ':' && i > 0) {
|
||||
// Valid scheme.
|
||||
scheme = data.substring(0, i);
|
||||
uri.append("intent:");
|
||||
data = data.substring(i+1);
|
||||
break;
|
||||
}
|
||||
|
||||
// No scheme.
|
||||
break;
|
||||
}
|
||||
}
|
||||
uri.append(data);
|
||||
|
||||
} else if ((flags&URI_INTENT_SCHEME) != 0) {
|
||||
uri.append("intent:");
|
||||
}
|
||||
|
||||
uri.append("#Intent;");
|
||||
|
||||
if (scheme != null) {
|
||||
uri.append("scheme=").append(scheme).append(';');
|
||||
}
|
||||
if (mAction != null) {
|
||||
uri.append("action=").append(mAction).append(';');
|
||||
uri.append("action=").append(Uri.encode(mAction)).append(';');
|
||||
}
|
||||
if (mCategories != null) {
|
||||
for (String category : mCategories) {
|
||||
uri.append("category=").append(category).append(';');
|
||||
uri.append("category=").append(Uri.encode(category)).append(';');
|
||||
}
|
||||
}
|
||||
if (mType != null) {
|
||||
uri.append("type=").append(mType).append(';');
|
||||
uri.append("type=").append(Uri.encode(mType, "/")).append(';');
|
||||
}
|
||||
if (mFlags != 0) {
|
||||
uri.append("launchFlags=0x").append(Integer.toHexString(mFlags)).append(';');
|
||||
}
|
||||
if (mPackage != null) {
|
||||
uri.append("package=").append(Uri.encode(mPackage)).append(';');
|
||||
}
|
||||
if (mComponent != null) {
|
||||
uri.append("component=").append(mComponent.flattenToShortString()).append(';');
|
||||
uri.append("component=").append(Uri.encode(
|
||||
mComponent.flattenToShortString(), "/")).append(';');
|
||||
}
|
||||
if (mExtras != null) {
|
||||
for (String key : mExtras.keySet()) {
|
||||
@ -4567,6 +4768,7 @@ public class Intent implements Parcelable {
|
||||
Uri.writeToParcel(out, mData);
|
||||
out.writeString(mType);
|
||||
out.writeInt(mFlags);
|
||||
out.writeString(mPackage);
|
||||
ComponentName.writeToParcel(mComponent, out);
|
||||
|
||||
if (mCategories != null) {
|
||||
@ -4600,6 +4802,7 @@ public class Intent implements Parcelable {
|
||||
mData = Uri.CREATOR.createFromParcel(in);
|
||||
mType = in.readString();
|
||||
mFlags = in.readInt();
|
||||
mPackage = in.readString();
|
||||
mComponent = ComponentName.readFromParcel(in);
|
||||
|
||||
int N = in.readInt();
|
||||
|
@ -82,9 +82,6 @@ interface IPackageManager {
|
||||
|
||||
ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags);
|
||||
|
||||
ResolveInfo resolveIntentForPackage(in Intent intent, String resolvedType, int flags,
|
||||
String packageName);
|
||||
|
||||
List<ResolveInfo> queryIntentActivities(in Intent intent,
|
||||
String resolvedType, int flags);
|
||||
|
||||
|
@ -985,23 +985,6 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
|
||||
|
||||
/**
|
||||
* Resolve the intent restricted to a package.
|
||||
* {@see #resolveActivity}
|
||||
*
|
||||
* @param intent An intent containing all of the desired specification
|
||||
* (action, data, type, category, and/or component).
|
||||
* @param flags Additional option flags. The most important is
|
||||
* MATCH_DEFAULT_ONLY, to limit the resolution to only
|
||||
* those activities that support the CATEGORY_DEFAULT.
|
||||
* @param packageName Restrict the intent resolution to this package.
|
||||
*
|
||||
* @return Returns a ResolveInfo containing the final activity intent that
|
||||
* was determined to be the best action. Returns null if no
|
||||
* matching activity was found.
|
||||
*/
|
||||
public abstract ResolveInfo resolveActivity(Intent intent, int flags, String packageName);
|
||||
|
||||
/**
|
||||
* Retrieve all activities that can be performed for the given intent.
|
||||
*
|
||||
|
@ -1269,28 +1269,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
return chooseBestActivity(intent, resolvedType, flags, query);
|
||||
}
|
||||
|
||||
public ResolveInfo resolveIntentForPackage(Intent intent, String resolvedType,
|
||||
int flags, String packageName) {
|
||||
ComponentName comp = intent.getComponent();
|
||||
if (comp != null) {
|
||||
// if this is an explicit intent, it must have the same the packageName
|
||||
if (packageName.equals(comp.getPackageName())) {
|
||||
return resolveIntent(intent, resolvedType, flags);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
List<ResolveInfo> query = null;
|
||||
synchronized (mPackages) {
|
||||
PackageParser.Package pkg = mPackages.get(packageName);
|
||||
if (pkg != null) {
|
||||
query = (List<ResolveInfo>) mActivities.
|
||||
queryIntentForPackage(intent, resolvedType, flags, pkg.activities);
|
||||
}
|
||||
}
|
||||
return chooseBestActivity(intent, resolvedType, flags, query);
|
||||
}
|
||||
}
|
||||
|
||||
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
|
||||
int flags, List<ResolveInfo> query) {
|
||||
if (query != null) {
|
||||
@ -1409,8 +1387,17 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
synchronized (mPackages) {
|
||||
return (List<ResolveInfo>)mActivities.
|
||||
queryIntent(intent, resolvedType, flags);
|
||||
String pkgName = intent.getPackage();
|
||||
if (pkgName == null) {
|
||||
return (List<ResolveInfo>)mActivities.queryIntent(intent,
|
||||
resolvedType, flags);
|
||||
}
|
||||
PackageParser.Package pkg = mPackages.get(pkgName);
|
||||
if (pkg != null) {
|
||||
return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
|
||||
resolvedType, flags, pkg.activities);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1577,9 +1564,30 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
public List<ResolveInfo> queryIntentReceivers(Intent intent,
|
||||
String resolvedType, int flags) {
|
||||
ComponentName comp = intent.getComponent();
|
||||
if (comp != null) {
|
||||
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
|
||||
ActivityInfo ai = getReceiverInfo(comp, flags);
|
||||
if (ai != null) {
|
||||
ResolveInfo ri = new ResolveInfo();
|
||||
ri.activityInfo = ai;
|
||||
list.add(ri);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
synchronized (mPackages) {
|
||||
return (List<ResolveInfo>)mReceivers.
|
||||
queryIntent(intent, resolvedType, flags);
|
||||
String pkgName = intent.getPackage();
|
||||
if (pkgName == null) {
|
||||
return (List<ResolveInfo>)mReceivers.queryIntent(intent,
|
||||
resolvedType, flags);
|
||||
}
|
||||
PackageParser.Package pkg = mPackages.get(pkgName);
|
||||
if (pkg != null) {
|
||||
return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
|
||||
resolvedType, flags, pkg.receivers);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1612,7 +1620,17 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
synchronized (mPackages) {
|
||||
return (List<ResolveInfo>)mServices.queryIntent(intent, resolvedType, flags);
|
||||
String pkgName = intent.getPackage();
|
||||
if (pkgName == null) {
|
||||
return (List<ResolveInfo>)mServices.queryIntent(intent,
|
||||
resolvedType, flags);
|
||||
}
|
||||
PackageParser.Package pkg = mPackages.get(pkgName);
|
||||
if (pkg != null) {
|
||||
return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
|
||||
resolvedType, flags, pkg.services);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3106,6 +3124,27 @@ class PackageManagerService extends IPackageManager.Stub {
|
||||
(flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
|
||||
}
|
||||
|
||||
public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
|
||||
ArrayList<PackageParser.Service> packageServices) {
|
||||
if (packageServices == null) {
|
||||
return null;
|
||||
}
|
||||
mFlags = flags;
|
||||
final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
|
||||
int N = packageServices.size();
|
||||
ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
|
||||
new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
|
||||
|
||||
ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
intentFilters = packageServices.get(i).intents;
|
||||
if (intentFilters != null && intentFilters.size() > 0) {
|
||||
listCut.add(intentFilters);
|
||||
}
|
||||
}
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
|
||||
}
|
||||
|
||||
public final void addService(PackageParser.Service s) {
|
||||
mServices.put(s.component, s);
|
||||
if (SHOW_INFO || Config.LOGV) Log.v(
|
||||
|
@ -7904,7 +7904,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
|
||||
// is there an Activity in this package that handles ACTION_APP_ERROR?
|
||||
Intent intent = new Intent(Intent.ACTION_APP_ERROR);
|
||||
ResolveInfo info = pm.resolveIntentForPackage(intent, null, 0, installerPackageName);
|
||||
intent.setPackage(installerPackageName);
|
||||
ResolveInfo info = pm.resolveIntent(intent, null, 0);
|
||||
if (info == null || info.activityInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -62,11 +62,6 @@ public class MockPackageManager extends PackageManager {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getPackageGids(String packageName) throws NameNotFoundException {
|
||||
throw new UnsupportedOperationException();
|
||||
|
Reference in New Issue
Block a user