Merge "Push chooser targets to the shortcut manager."
This commit is contained in:
committed by
Android (Google) Code Review
commit
1058a3dd95
@@ -55,7 +55,8 @@ interface ILauncherApps {
|
||||
String callingPackage, String packageName, int flags, in UserHandle user);
|
||||
|
||||
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
|
||||
in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
|
||||
in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
|
||||
in UserHandle user);
|
||||
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
|
||||
in UserHandle user);
|
||||
boolean startShortcut(String callingPackage, String packageName, String id,
|
||||
|
||||
@@ -275,7 +275,18 @@ public class LauncherApps {
|
||||
@Deprecated
|
||||
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
|
||||
|
||||
/** @hide */
|
||||
/**
|
||||
* Include chooser shortcuts in the result.
|
||||
* STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
|
||||
* relevant fields from the Shortcut. This should also be adequately documented.
|
||||
*/
|
||||
public static final int FLAG_MATCH_CHOOSER = 1 << 4;
|
||||
|
||||
/**
|
||||
* Does not retrieve CHOOSER only shortcuts.
|
||||
* TODO: Add another flag for MATCH_ALL_PINNED
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_MATCH_ALL_KINDS =
|
||||
FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
|
||||
|
||||
@@ -308,6 +319,7 @@ public class LauncherApps {
|
||||
FLAG_MATCH_DYNAMIC,
|
||||
FLAG_MATCH_PINNED,
|
||||
FLAG_MATCH_MANIFEST,
|
||||
FLAG_MATCH_CHOOSER,
|
||||
FLAG_GET_KEY_FIELDS_ONLY,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -324,6 +336,9 @@ public class LauncherApps {
|
||||
@Nullable
|
||||
ComponentName mActivity;
|
||||
|
||||
@Nullable
|
||||
Intent mIntent;
|
||||
|
||||
@QueryFlags
|
||||
int mQueryFlags;
|
||||
|
||||
@@ -367,6 +382,14 @@ public class LauncherApps {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If non-null, returns only shortcuts with intent filters that match this intent.
|
||||
*/
|
||||
public ShortcutQuery setIntent(@Nullable Intent intent) {
|
||||
mIntent = intent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
|
||||
* no shortcuts will be returned.
|
||||
@@ -681,7 +704,7 @@ public class LauncherApps {
|
||||
try {
|
||||
return mService.getShortcuts(mContext.getPackageName(),
|
||||
query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
|
||||
query.mQueryFlags, user)
|
||||
query.mIntent, query.mQueryFlags, user)
|
||||
.getList();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -21,8 +21,10 @@ import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.LauncherApps.ShortcutQuery;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
@@ -38,10 +40,12 @@ import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.MemInfoReader;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -95,6 +99,14 @@ public final class ShortcutInfo implements Parcelable {
|
||||
public static final int FLAG_MASKABLE_BITMAP = 1 << 9;
|
||||
|
||||
/** @hide */
|
||||
public static final int FLAG_CHOOSER = 1 << 10;
|
||||
|
||||
/**
|
||||
* TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
|
||||
* due to the context in which it was retrieved.
|
||||
* TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
|
||||
* @hide
|
||||
*/
|
||||
@IntDef(flag = true,
|
||||
value = {
|
||||
FLAG_DYNAMIC,
|
||||
@@ -107,6 +119,7 @@ public final class ShortcutInfo implements Parcelable {
|
||||
FLAG_STRINGS_RESOLVED,
|
||||
FLAG_IMMUTABLE,
|
||||
FLAG_MASKABLE_BITMAP,
|
||||
FLAG_CHOOSER,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ShortcutFlags {}
|
||||
@@ -201,6 +214,24 @@ public final class ShortcutInfo implements Parcelable {
|
||||
@Nullable
|
||||
private PersistableBundle[] mIntentPersistableExtrases;
|
||||
|
||||
/**
|
||||
* If used in a chooser, extras that should be added into the intent passed through.
|
||||
*/
|
||||
@Nullable
|
||||
private PersistableBundle mChooserExtras;
|
||||
|
||||
/**
|
||||
* Intent filters to be used if the shortcut is to be used in a chooser context.
|
||||
*/
|
||||
@Nullable
|
||||
private IntentFilter[] mChooserIntentFilters;
|
||||
|
||||
/**
|
||||
* Component names corresponding to the above intent filters.
|
||||
*/
|
||||
@Nullable
|
||||
private ComponentName[] mChooserComponentNames;
|
||||
|
||||
private int mRank;
|
||||
|
||||
/**
|
||||
@@ -250,6 +281,13 @@ public final class ShortcutInfo implements Parcelable {
|
||||
mDisabledMessageResId = b.mDisabledMessageResId;
|
||||
mCategories = cloneCategories(b.mCategories);
|
||||
mIntents = cloneIntents(b.mIntents);
|
||||
if (b.mChooserIntentFilters != null) {
|
||||
mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
|
||||
}
|
||||
if (b.mChooserComponentNames != null) {
|
||||
mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
|
||||
}
|
||||
mChooserExtras = b.mChooserExtras;
|
||||
fixUpIntentExtras();
|
||||
mRank = b.mRank;
|
||||
mExtras = b.mExtras;
|
||||
@@ -330,8 +368,28 @@ public final class ShortcutInfo implements Parcelable {
|
||||
if (mTitle == null && mTitleResId == 0) {
|
||||
throw new IllegalArgumentException("Short label must be provided");
|
||||
}
|
||||
Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
|
||||
Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
|
||||
|
||||
// For a shortcut to be valid, there should either be an Intent, or a non-empty set of
|
||||
// intent filters.
|
||||
if (mIntents == null || mIntents.length == 0) {
|
||||
Preconditions.checkNotNull(mChooserIntentFilters,
|
||||
"Intent must be provided if not a chooser target");
|
||||
Preconditions.checkNotNull(mChooserComponentNames,
|
||||
"Intent must be provided if not a chooser target");
|
||||
}
|
||||
|
||||
// If ChooserIntentFilter are provided, they should match the length of the provided
|
||||
// component names.
|
||||
if (mChooserIntentFilters != null) {
|
||||
if (mChooserComponentNames == null
|
||||
|| mChooserIntentFilters.length != mChooserComponentNames.length) {
|
||||
throw new IllegalArgumentException("Inconsistent intent filters and "
|
||||
+ "component names given");
|
||||
}
|
||||
if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
|
||||
throw new IllegalArgumentException("Empty intent filter and component names given");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,6 +434,10 @@ public final class ShortcutInfo implements Parcelable {
|
||||
mDisabledMessageResName = source.mDisabledMessageResName;
|
||||
mIconResName = source.mIconResName;
|
||||
}
|
||||
// TODO: Omit these by default and add a new clone flag.
|
||||
mChooserIntentFilters = source.mChooserIntentFilters;
|
||||
mChooserComponentNames = source.mChooserComponentNames;
|
||||
mChooserExtras = source.mChooserExtras;
|
||||
} else {
|
||||
// Set this bit.
|
||||
mFlags |= FLAG_KEY_FIELDS_ONLY;
|
||||
@@ -502,6 +564,25 @@ public final class ShortcutInfo implements Parcelable {
|
||||
return fullResourceName.substring(p1 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the shortcut has any intentFilter matching the passed in one.
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
|
||||
if (mChooserIntentFilters == null) {
|
||||
return false;
|
||||
}
|
||||
for (IntentFilter filter : mChooserIntentFilters) {
|
||||
int match = filter.match(resolver, intent, false, TAG);
|
||||
if (match > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the entry name from a fully-donated resource name.
|
||||
* e.g. "com.android.app1:drawable/icon1" -> "icon1"
|
||||
@@ -685,6 +766,15 @@ public final class ShortcutInfo implements Parcelable {
|
||||
if (source.mExtras != null) {
|
||||
mExtras = source.mExtras;
|
||||
}
|
||||
if (source.mChooserExtras != null) {
|
||||
mChooserExtras = source.mChooserExtras;
|
||||
}
|
||||
if (source.mChooserIntentFilters != null) {
|
||||
mChooserIntentFilters = source.mChooserIntentFilters;
|
||||
}
|
||||
if (source.mChooserComponentNames != null) {
|
||||
mChooserComponentNames = source.mChooserComponentNames;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,6 +836,12 @@ public final class ShortcutInfo implements Parcelable {
|
||||
|
||||
private PersistableBundle mExtras;
|
||||
|
||||
private PersistableBundle mChooserExtras;
|
||||
|
||||
private List<IntentFilter> mChooserIntentFilters;
|
||||
|
||||
private List<ComponentName> mChooserComponentNames;
|
||||
|
||||
/**
|
||||
* Old style constructor.
|
||||
* @hide
|
||||
@@ -1031,6 +1127,40 @@ public final class ShortcutInfo implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extras that can be added which will be added to the Intent used to launch the app if
|
||||
* launched from a chooser context.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setChooserExtras(@NonNull PersistableBundle extras) {
|
||||
mChooserExtras = extras;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* IntentFilters and the components that should resolve a match for a given chooser target.
|
||||
* If multiple matches are found, the component corresponding to the closest match will be
|
||||
* used.
|
||||
*
|
||||
* @param filter IntendFilter that if matched will have the intent forwarded to the given
|
||||
* component
|
||||
* @param name The component that an intent that passes this filter will resolve to.
|
||||
*/
|
||||
public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
|
||||
@NonNull ComponentName name) {
|
||||
Preconditions.checkNotNull(filter, "intent filter cannot be null");
|
||||
Preconditions.checkNotNull(name, "component name cannot be null");
|
||||
|
||||
if (mChooserIntentFilters == null || mChooserComponentNames == null) {
|
||||
mChooserIntentFilters = new ArrayList<>();
|
||||
mChooserComponentNames = new ArrayList<>();
|
||||
}
|
||||
|
||||
mChooserIntentFilters.add(filter);
|
||||
mChooserComponentNames.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ShortcutInfo} instance.
|
||||
*/
|
||||
@@ -1231,6 +1361,30 @@ public final class ShortcutInfo implements Parcelable {
|
||||
return mIntentPersistableExtrases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the extras that will be added in to any intent launched through the chooser.
|
||||
*/
|
||||
@NonNull
|
||||
public PersistableBundle getChooserExtras() {
|
||||
return mChooserExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of intent filters for chooser targets.
|
||||
*/
|
||||
@NonNull
|
||||
public IntentFilter[] getChooserIntentFilters() {
|
||||
return mChooserIntentFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of component names corresponding to the above intent filters.
|
||||
*/
|
||||
@NonNull
|
||||
public ComponentName[] getChooserComponentNames() {
|
||||
return mChooserComponentNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
|
||||
* {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
|
||||
@@ -1352,6 +1506,11 @@ public final class ShortcutInfo implements Parcelable {
|
||||
return hasFlags(FLAG_PINNED);
|
||||
}
|
||||
|
||||
/** Return whether a shortcut can be shown in the chooser. */
|
||||
public boolean isChooser() {
|
||||
return hasFlags(FLAG_CHOOSER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a shortcut is static; that is, whether a shortcut is
|
||||
* published from AndroidManifest.xml. If {@code true}, the shortcut is
|
||||
@@ -1380,6 +1539,14 @@ public final class ShortcutInfo implements Parcelable {
|
||||
return isPinned() && !(isDynamic() || isManifestShortcut());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if pinned but neither static nor dynamic.
|
||||
* @hide
|
||||
*/
|
||||
public boolean isDynamicOrChooser() {
|
||||
return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean isOriginallyFromManifest() {
|
||||
return hasFlags(FLAG_IMMUTABLE);
|
||||
@@ -1661,6 +1828,19 @@ public final class ShortcutInfo implements Parcelable {
|
||||
mCategories.add(source.readString().intern());
|
||||
}
|
||||
}
|
||||
|
||||
// We put a placeholder empty array in to keep the parcelable order, but can do away with
|
||||
// them at this point if they're empty.
|
||||
mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
|
||||
if (mChooserComponentNames.length == 0) {
|
||||
mChooserComponentNames = null;
|
||||
}
|
||||
|
||||
mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
|
||||
if (mChooserIntentFilters.length == 0) {
|
||||
mChooserIntentFilters = null;
|
||||
}
|
||||
mChooserExtras = source.readPersistableBundle(cl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1707,6 +1887,17 @@ public final class ShortcutInfo implements Parcelable {
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
if (mChooserComponentNames != null) {
|
||||
dest.writeParcelableArray(mChooserComponentNames, flags);
|
||||
} else {
|
||||
dest.writeParcelableArray(new ComponentName[0], flags);
|
||||
}
|
||||
if (mChooserIntentFilters != null) {
|
||||
dest.writeParcelableArray(mChooserIntentFilters, flags);
|
||||
} else {
|
||||
dest.writeParcelableArray(new IntentFilter[0], flags);
|
||||
}
|
||||
dest.writePersistableBundle(mChooserExtras);
|
||||
}
|
||||
|
||||
public static final Creator<ShortcutInfo> CREATOR =
|
||||
|
||||
@@ -44,8 +44,8 @@ public abstract class ShortcutServiceInternal {
|
||||
getShortcuts(int launcherUserId,
|
||||
@NonNull String callingPackage, long changedSince,
|
||||
@Nullable String packageName, @Nullable List<String> shortcutIds,
|
||||
@Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
|
||||
int userId);
|
||||
@Nullable ComponentName componentName, @Nullable Intent intent,
|
||||
@ShortcutQuery.QueryFlags int flags, int userId);
|
||||
|
||||
public abstract boolean
|
||||
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
|
||||
|
||||
@@ -23,15 +23,21 @@ import android.app.usage.UsageStatsManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentSender;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.LabeledIntent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -356,6 +362,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
|
||||
}
|
||||
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
|
||||
mChooserRowAdapter.updateRowScales();
|
||||
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
|
||||
adapterView.setAdapter(mChooserRowAdapter);
|
||||
if (listView != null) {
|
||||
@@ -842,7 +849,9 @@ public class ChooserActivity extends ResolverActivity {
|
||||
return false;
|
||||
}
|
||||
intent.setComponent(mChooserTarget.getComponentName());
|
||||
intent.putExtras(mChooserTarget.getIntentExtras());
|
||||
if (mChooserTarget.getIntentExtras() != null) {
|
||||
intent.putExtras(mChooserTarget.getIntentExtras());
|
||||
}
|
||||
|
||||
// Important: we will ignore the target security checks in ActivityManager
|
||||
// if and only if the ChooserTarget's target package is the same package
|
||||
@@ -925,6 +934,8 @@ public class ChooserActivity extends ResolverActivity {
|
||||
private static final int MAX_SERVICE_TARGETS = 8;
|
||||
private static final int MAX_TARGETS_PER_SERVICE = 4;
|
||||
|
||||
private boolean mAreChooserShortcutsRetrieved;
|
||||
|
||||
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
|
||||
private final List<TargetInfo> mCallerTargets = new ArrayList<>();
|
||||
private boolean mShowServiceTargets;
|
||||
@@ -1016,6 +1027,20 @@ public class ChooserActivity extends ResolverActivity {
|
||||
if (mServiceTargets != null) {
|
||||
pruneServiceTargets();
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
|
||||
|
||||
if (!mAreChooserShortcutsRetrieved) {
|
||||
LauncherApps launcherApps = getLauncherApps();
|
||||
LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
|
||||
query.setIntent(getTargetIntent());
|
||||
query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
|
||||
List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query, UserHandle.SYSTEM);
|
||||
if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
|
||||
addShortcuts(shortcuts);
|
||||
mAreChooserShortcutsRetrieved = true;
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "List built querying services");
|
||||
queryTargetServices(this);
|
||||
}
|
||||
@@ -1041,6 +1066,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
|
||||
public int getServiceTargetCount() {
|
||||
if (!mShowServiceTargets) {
|
||||
if (DEBUG) Log.d("TAG", "Hiding service targets");
|
||||
return 0;
|
||||
}
|
||||
return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
|
||||
@@ -1132,6 +1158,71 @@ public class ChooserActivity extends ResolverActivity {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
// TODO: Pushed targets need to be scored correctly
|
||||
public void addShortcuts(List<ShortcutInfo> infos) {
|
||||
for (ShortcutInfo info : infos) {
|
||||
List<ChooserTarget> newTargets = new ArrayList<>();
|
||||
final ComponentName cn = info.getActivity();
|
||||
ActivityInfo ai;
|
||||
ResolveInfo ri = new ResolveInfo();
|
||||
if (cn != null) {
|
||||
try {
|
||||
ai = getPackageManager().getActivityInfo(cn, 0);
|
||||
ri.activityInfo = ai;
|
||||
UserManager userManager =
|
||||
(UserManager) getSystemService(Context.USER_SERVICE);
|
||||
ri.iconResourceId = ai.icon;
|
||||
ri.labelRes = ai.labelRes;
|
||||
ri.resolvePackageName = ai.packageName;
|
||||
ri.activityInfo.applicationInfo = new ApplicationInfo(
|
||||
ri.activityInfo.applicationInfo);
|
||||
ri.activityInfo.applicationInfo = ai.applicationInfo;
|
||||
ri.activityInfo.applicationInfo.uid = getUserId();
|
||||
} catch (PackageManager.NameNotFoundException ignored) {
|
||||
if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
|
||||
ri,
|
||||
info.getShortLabel(),
|
||||
info.getLongLabel(),
|
||||
getTargetIntent());
|
||||
|
||||
int bestMatch = 0;
|
||||
ComponentName bestComponent = null;
|
||||
for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
|
||||
int newMatch = info.getChooserIntentFilters()[i]
|
||||
.match(getContentResolver(), getTargetIntent(), false, TAG);
|
||||
if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
|
||||
if (newMatch > bestMatch) {
|
||||
bestMatch = newMatch;
|
||||
bestComponent = info.getChooserComponentNames()[i];
|
||||
}
|
||||
}
|
||||
if (bestMatch == 0) {
|
||||
Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
|
||||
return;
|
||||
}
|
||||
|
||||
Bundle extrasToAdd =
|
||||
info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
|
||||
if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
|
||||
newTargets.add(new ChooserTarget(
|
||||
info.getShortLabel(),
|
||||
info.getIcon(),
|
||||
1,
|
||||
bestComponent,
|
||||
extrasToAdd));
|
||||
addServiceResults(resolveInfo, newTargets);
|
||||
}
|
||||
if (mChooserRowAdapter != null) {
|
||||
mChooserRowAdapter.updateRowScales();
|
||||
}
|
||||
setShowServiceTargets(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to reveal all service targets at once.
|
||||
*/
|
||||
@@ -1246,37 +1337,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
final int rcount = getServiceTargetRowCount();
|
||||
if (mServiceTargetScale == null
|
||||
|| mServiceTargetScale.length != rcount) {
|
||||
RowScale[] old = mServiceTargetScale;
|
||||
int oldRCount = old != null ? old.length : 0;
|
||||
mServiceTargetScale = new RowScale[rcount];
|
||||
if (old != null && rcount > 0) {
|
||||
System.arraycopy(old, 0, mServiceTargetScale, 0,
|
||||
Math.min(old.length, rcount));
|
||||
}
|
||||
|
||||
for (int i = rcount; i < oldRCount; i++) {
|
||||
old[i].cancelAnimation();
|
||||
}
|
||||
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
|
||||
.setInterpolator(mInterpolator);
|
||||
mServiceTargetScale[i] = rs;
|
||||
}
|
||||
|
||||
// Start the animations in a separate loop.
|
||||
// The process of starting animations will result in
|
||||
// binding views to set up initial values, and we must
|
||||
// have ALL of the new RowScale objects created above before
|
||||
// we get started.
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
mServiceTargetScale[i].startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
updateRowScales();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@@ -1293,6 +1354,40 @@ public class ChooserActivity extends ResolverActivity {
|
||||
});
|
||||
}
|
||||
|
||||
void updateRowScales() {
|
||||
final int rcount = getServiceTargetRowCount();
|
||||
if (mServiceTargetScale == null
|
||||
|| mServiceTargetScale.length != rcount) {
|
||||
if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
|
||||
RowScale[] old = mServiceTargetScale;
|
||||
int oldRCount = old != null ? old.length : 0;
|
||||
mServiceTargetScale = new RowScale[rcount];
|
||||
if (old != null && rcount > 0) {
|
||||
System.arraycopy(old, 0, mServiceTargetScale, 0,
|
||||
Math.min(old.length, rcount));
|
||||
}
|
||||
|
||||
for (int i = rcount; i < oldRCount; i++) {
|
||||
old[i].cancelAnimation();
|
||||
}
|
||||
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
|
||||
.setInterpolator(mInterpolator);
|
||||
mServiceTargetScale[i] = rs;
|
||||
}
|
||||
|
||||
// Start the animations in a separate loop.
|
||||
// The process of starting animations will result in
|
||||
// binding views to set up initial values, and we must
|
||||
// have ALL of the new RowScale objects created above before
|
||||
// we get started.
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
mServiceTargetScale[i].startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float getRowScale(int rowPosition) {
|
||||
final int start = getCallerTargetRowCount();
|
||||
final int end = start + getServiceTargetRowCount();
|
||||
@@ -1563,6 +1658,10 @@ public class ChooserActivity extends ResolverActivity {
|
||||
}
|
||||
}
|
||||
|
||||
public LauncherApps getLauncherApps() {
|
||||
return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
|
||||
}
|
||||
|
||||
static class ServiceResultInfo {
|
||||
public final DisplayResolveInfo originalTarget;
|
||||
public final List<ChooserTarget> resultTargets;
|
||||
|
||||
Reference in New Issue
Block a user