diff options
| author | 2022-12-12 09:17:29 -0800 | |
|---|---|---|
| committer | 2023-01-05 10:18:51 -0800 | |
| commit | 49b65f54be53ec48d53a550e783759100e8812dc (patch) | |
| tree | a9c9a5ba553f0fddaae5a74b6dec9641d6c18881 /java/src/com | |
| parent | c317e6a26b75da0a693cbb14f673ecdd7152c433 (diff) | |
Add Chooser custom actions
Add Chooser custom action support under a compile-time flag.
Bug: 262278109
Test: manual testing of the basic functionality
Test: manual custom actions testing with a test app
Test: atest IntentResolverUnitTests (with the both flag values)
Change-Id: Ib6f6b46aa4f693a544e0e52a6d1a3e63ba57b162
Diffstat (limited to 'java/src/com')
3 files changed, 91 insertions, 6 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index ceab62b2..55904fc1 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.PendingIntent; import android.app.prediction.AppPredictor; import android.app.prediction.AppTarget; import android.app.prediction.AppTargetEvent; @@ -70,6 +71,7 @@ import android.os.UserManager; import android.os.storage.StorageManager; import android.provider.DeviceConfig; import android.provider.Settings; +import android.service.chooser.ChooserAction; import android.service.chooser.ChooserTarget; import android.text.TextUtils; import android.util.Log; @@ -112,6 +114,8 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import com.google.common.collect.ImmutableList; + import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; @@ -158,6 +162,7 @@ public class ChooserActivity extends ResolverActivity implements private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon"; private static final boolean DEBUG = true; + static final boolean ENABLE_CUSTOM_ACTIONS = false; public static final String LAUNCH_LOCATION_DIRECT_SHARE = "direct_share"; private static final String SHORTCUT_TARGET = "shortcut_target"; @@ -265,7 +270,7 @@ public class ChooserActivity extends ResolverActivity implements try { mChooserRequest = new ChooserRequestParameters( - getIntent(), getReferrer(), getNearbySharingComponent()); + getIntent(), getReferrer(), getNearbySharingComponent(), ENABLE_CUSTOM_ACTIONS); } catch (IllegalArgumentException e) { Log.e(TAG, "Caller provided invalid Chooser request parameters", e); finish(); @@ -732,6 +737,20 @@ public class ChooserActivity extends ResolverActivity implements public ActionRow.Action createNearbyButton() { return ChooserActivity.this.createNearbyAction(targetIntent); } + + @Override + public List<ActionRow.Action> createCustomActions() { + ImmutableList<ChooserAction> customActions = + mChooserRequest.getChooserActions(); + List<ActionRow.Action> actions = new ArrayList<>(customActions.size()); + for (ChooserAction customAction : customActions) { + ActionRow.Action action = createCustomAction(customAction); + if (action != null) { + actions.add(action); + } + } + return actions; + } }; ViewGroup layout = ChooserContentPreviewUi.displayContentPreview( @@ -740,7 +759,9 @@ public class ChooserActivity extends ResolverActivity implements getResources(), getLayoutInflater(), actionFactory, - R.layout.chooser_action_row, + ENABLE_CUSTOM_ACTIONS + ? R.layout.scrollable_chooser_action_row + : R.layout.chooser_action_row, parent, previewCoordinator, mEnterTransitionAnimationDelegate::markImagePreviewReady, @@ -928,6 +949,28 @@ public class ChooserActivity extends ResolverActivity implements } @Nullable + private ActionRow.Action createCustomAction(ChooserAction action) { + Drawable icon = action.getIcon().loadDrawable(this); + if (icon == null && TextUtils.isEmpty(action.getLabel())) { + return null; + } + return new ActionRow.Action( + action.getLabel(), + icon, + () -> { + try { + action.getAction().send(); + } catch (PendingIntent.CanceledException e) { + Log.d(TAG, "Custom action, " + action.getLabel() + ", has been cancelled"); + } + // TODO: add reporting + setResult(RESULT_OK); + finish(); + } + ); + } + + @Nullable private View getFirstVisibleImgPreviewView() { View firstImage = findViewById(com.android.internal.R.id.content_preview_image_1_large); return firstImage != null && firstImage.isVisibleToUser() ? firstImage : null; diff --git a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java index ff88e5e1..daded28b 100644 --- a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java @@ -102,6 +102,9 @@ public final class ChooserContentPreviewUi { /** Create an "Share to Nearby" action. */ @Nullable ActionRow.Action createNearbyButton(); + + /** Create custom actions */ + List<ActionRow.Action> createCustomActions(); } /** @@ -187,12 +190,15 @@ public final class ChooserContentPreviewUi { ImageMimeTypeClassifier imageClassifier) { ViewGroup layout = null; + List<ActionRow.Action> customActions = actionFactory.createCustomActions(); switch (previewType) { case CONTENT_PREVIEW_TEXT: layout = displayTextContentPreview( targetIntent, layoutInflater, - createTextPreviewActions(actionFactory), + createActions( + createTextPreviewActions(actionFactory), + customActions), parent, previewCoord, actionRowLayout); @@ -201,7 +207,9 @@ public final class ChooserContentPreviewUi { layout = displayImageContentPreview( targetIntent, layoutInflater, - createImagePreviewActions(actionFactory), + createActions( + createImagePreviewActions(actionFactory), + customActions), parent, previewCoord, onTransitionTargetReady, @@ -214,7 +222,9 @@ public final class ChooserContentPreviewUi { targetIntent, resources, layoutInflater, - createFilePreviewActions(actionFactory), + createActions( + createFilePreviewActions(actionFactory), + customActions), parent, previewCoord, contentResolver, @@ -227,6 +237,17 @@ public final class ChooserContentPreviewUi { return layout; } + private static List<ActionRow.Action> createActions( + List<ActionRow.Action> systemActions, List<ActionRow.Action> customActions) { + ArrayList<ActionRow.Action> actions = + new ArrayList<>(systemActions.size() + customActions.size()); + actions.addAll(systemActions); + if (ChooserActivity.ENABLE_CUSTOM_ACTIONS) { + actions.addAll(customActions); + } + return actions; + } + private static Cursor queryResolver(ContentResolver resolver, Uri uri) { return resolver.query(uri, null, null, null, null); } diff --git a/java/src/com/android/intentresolver/ChooserRequestParameters.java b/java/src/com/android/intentresolver/ChooserRequestParameters.java index 81481bf1..a7e543a5 100644 --- a/java/src/com/android/intentresolver/ChooserRequestParameters.java +++ b/java/src/com/android/intentresolver/ChooserRequestParameters.java @@ -26,6 +26,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.os.PatternMatcher; +import android.service.chooser.ChooserAction; import android.service.chooser.ChooserTarget; import android.text.TextUtils; import android.util.Log; @@ -70,6 +71,7 @@ public class ChooserRequestParameters { private final Intent mReferrerFillInIntent; private final ImmutableList<ComponentName> mFilteredComponentNames; private final ImmutableList<ChooserTarget> mCallerChooserTargets; + private final ImmutableList<ChooserAction> mChooserActions; private final boolean mRetainInOnStop; @Nullable @@ -96,7 +98,8 @@ public class ChooserRequestParameters { public ChooserRequestParameters( final Intent clientIntent, final Uri referrer, - @Nullable final ComponentName nearbySharingComponent) { + @Nullable final ComponentName nearbySharingComponent, + boolean extractCustomActions) { final Intent requestedTarget = parseTargetIntentExtra( clientIntent.getParcelableExtra(Intent.EXTRA_INTENT)); mTarget = intentWithModifiedLaunchFlags(requestedTarget); @@ -130,6 +133,10 @@ public class ChooserRequestParameters { mSharedText = mTarget.getStringExtra(Intent.EXTRA_TEXT); mTargetIntentFilter = getTargetIntentFilter(mTarget); + + mChooserActions = extractCustomActions + ? getChooserActions(clientIntent) + : ImmutableList.of(); } public Intent getTargetIntent() { @@ -171,6 +178,10 @@ public class ChooserRequestParameters { return mCallerChooserTargets; } + public ImmutableList<ChooserAction> getChooserActions() { + return mChooserActions; + } + /** * Whether the {@link ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP} behavior was requested. */ @@ -300,6 +311,16 @@ public class ChooserRequestParameters { .collect(toImmutableList()); } + private static ImmutableList<ChooserAction> getChooserActions(Intent intent) { + return streamParcelableArrayExtra( + intent, + Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, + ChooserAction.class, + true, + true) + .collect(toImmutableList()); + } + private static <T> Collector<T, ?, ImmutableList<T>> toImmutableList() { return Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf); } |