Screenshot to share sheet shared element transition.
Switching the share action to a Supplier interface allows us to maintain the current code style, while ensuring that the APIs required to start the transition are called when the share chip is pressed. Bug: 174811491 Test: manual Change-Id: I201b82eaea650fcef23909212385fd6d56831429
This commit is contained in:
@@ -28,6 +28,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.SharedElementCallback;
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppPredictionManager;
|
||||
import android.app.prediction.AppPredictor;
|
||||
@@ -176,6 +177,13 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
|
||||
= "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
|
||||
|
||||
/**
|
||||
* Transition name for the first image preview.
|
||||
* To be used for shared element transition into this activity.
|
||||
* @hide
|
||||
*/
|
||||
public static final String FIRST_IMAGE_PREVIEW_TRANSITION_NAME = "chooser_preview_image_1";
|
||||
|
||||
private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
|
||||
|
||||
private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
|
||||
@@ -307,6 +315,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
@VisibleForTesting
|
||||
protected ChooserMultiProfilePagerAdapter mChooserMultiProfilePagerAdapter;
|
||||
|
||||
private boolean mRemoveSharedElements = false;
|
||||
|
||||
private class ContentPreviewCoordinator {
|
||||
private static final int IMAGE_FADE_IN_MILLIS = 150;
|
||||
private static final int IMAGE_LOAD_TIMEOUT = 1;
|
||||
@@ -370,10 +380,29 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
if (task.mExtraCount > 0) {
|
||||
imageView.setExtraImageCount(task.mExtraCount);
|
||||
}
|
||||
|
||||
setupPreDrawForSharedElementTransition(imageView);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void setupPreDrawForSharedElementTransition(View v) {
|
||||
v.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
v.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
if (!mRemoveSharedElements && isActivityTransitionRunning()) {
|
||||
// Disable the window animations as it interferes with the
|
||||
// transition animation.
|
||||
getWindow().setWindowAnimations(0);
|
||||
}
|
||||
startPostponedEnterTransition();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ContentPreviewCoordinator(View parentView, boolean hideParentOnFail) {
|
||||
super();
|
||||
|
||||
@@ -413,6 +442,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
mHideParentOnFail = false;
|
||||
}
|
||||
mRemoveSharedElements = true;
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
private void collapseParentView() {
|
||||
@@ -794,6 +825,19 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
);
|
||||
mDirectShareShortcutInfoCache = new HashMap<>();
|
||||
mChooserTargetComponentNameCache = new HashMap<>();
|
||||
|
||||
setEnterSharedElementCallback(new SharedElementCallback() {
|
||||
@Override
|
||||
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
|
||||
if (mRemoveSharedElements) {
|
||||
names.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
|
||||
sharedElements.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
|
||||
}
|
||||
super.onMapSharedElements(names, sharedElements);
|
||||
mRemoveSharedElements = false;
|
||||
}
|
||||
});
|
||||
postponeEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1337,6 +1381,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
String action = targetIntent.getAction();
|
||||
if (Intent.ACTION_SEND.equals(action)) {
|
||||
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
imagePreview.findViewById(R.id.content_preview_image_1_large)
|
||||
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
|
||||
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
|
||||
} else {
|
||||
ContentResolver resolver = getContentResolver();
|
||||
@@ -1356,6 +1402,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
return contentPreviewLayout;
|
||||
}
|
||||
|
||||
imagePreview.findViewById(R.id.content_preview_image_1_large)
|
||||
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
|
||||
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), 0);
|
||||
|
||||
if (imageUris.size() == 2) {
|
||||
|
||||
@@ -56,6 +56,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SystemUIFactory;
|
||||
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -74,6 +75,7 @@ import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* An AsyncTask that saves an image to the media store in the background.
|
||||
@@ -95,12 +97,15 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
|
||||
private final String mScreenshotId;
|
||||
private final boolean mSmartActionsEnabled;
|
||||
private final Random mRandom = new Random();
|
||||
private final Supplier<ShareTransition> mSharedElementTransition;
|
||||
|
||||
SaveImageInBackgroundTask(Context context, ScreenshotSmartActions screenshotSmartActions,
|
||||
ScreenshotController.SaveImageInBackgroundData data) {
|
||||
ScreenshotController.SaveImageInBackgroundData data,
|
||||
Supplier<ShareTransition> sharedElementTransition) {
|
||||
mContext = context;
|
||||
mScreenshotSmartActions = screenshotSmartActions;
|
||||
mImageData = new ScreenshotController.SavedImageData();
|
||||
mSharedElementTransition = sharedElementTransition;
|
||||
|
||||
// Prepare all the output metadata
|
||||
mParams = data;
|
||||
@@ -135,7 +140,6 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
Bitmap image = mParams.image;
|
||||
Resources r = mContext.getResources();
|
||||
|
||||
try {
|
||||
// Save the screenshot to the MediaStore
|
||||
@@ -233,7 +237,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
mImageData.uri = uri;
|
||||
mImageData.smartActions = smartActions;
|
||||
mImageData.shareAction = createShareAction(mContext, mContext.getResources(), uri);
|
||||
mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
|
||||
mImageData.editAction = createEditAction(mContext, mContext.getResources(), uri);
|
||||
mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
|
||||
|
||||
@@ -284,61 +288,68 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
|
||||
mParams.clearImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the action intent is sent immediately after being supplied.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
Notification.Action createShareAction(Context context, Resources r, Uri uri) {
|
||||
// Note: Both the share and edit actions are proxied through ActionProxyReceiver in
|
||||
// order to do some common work like dismissing the keyguard and sending
|
||||
// closeSystemWindows
|
||||
Supplier<ShareTransition> createShareAction(Context context, Resources r, Uri uri) {
|
||||
return () -> {
|
||||
ShareTransition transition = mSharedElementTransition.get();
|
||||
|
||||
// Create a share intent, this will always go through the chooser activity first
|
||||
// which should not trigger auto-enter PiP
|
||||
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
|
||||
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
|
||||
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
|
||||
sharingIntent.setType("image/png");
|
||||
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
// Include URI in ClipData also, so that grantPermission picks it up.
|
||||
// We don't use setData here because some apps interpret this as "to:".
|
||||
ClipData clipdata = new ClipData(new ClipDescription("content",
|
||||
new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
|
||||
new ClipData.Item(uri));
|
||||
sharingIntent.setClipData(clipdata);
|
||||
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
// Note: Both the share and edit actions are proxied through ActionProxyReceiver in
|
||||
// order to do some common work like dismissing the keyguard and sending
|
||||
// closeSystemWindows
|
||||
|
||||
// Make sure pending intents for the system user are still unique across users
|
||||
// by setting the (otherwise unused) request code to the current user id.
|
||||
int requestCode = context.getUserId();
|
||||
// Create a share intent, this will always go through the chooser activity first
|
||||
// which should not trigger auto-enter PiP
|
||||
String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
|
||||
String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
|
||||
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
|
||||
sharingIntent.setType("image/png");
|
||||
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
// Include URI in ClipData also, so that grantPermission picks it up.
|
||||
// We don't use setData here because some apps interpret this as "to:".
|
||||
ClipData clipdata = new ClipData(new ClipDescription("content",
|
||||
new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
|
||||
new ClipData.Item(uri));
|
||||
sharingIntent.setClipData(clipdata);
|
||||
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
Intent sharingChooserIntent =
|
||||
Intent.createChooser(sharingIntent, null)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
// Make sure pending intents for the system user are still unique across users
|
||||
// by setting the (otherwise unused) request code to the current user id.
|
||||
int requestCode = context.getUserId();
|
||||
|
||||
// cancel current pending intent (if any) since clipData isn't used for matching
|
||||
PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
|
||||
context, 0, sharingChooserIntent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
|
||||
null, UserHandle.CURRENT);
|
||||
Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
// Create a share action for the notification
|
||||
PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
|
||||
new Intent(context, ActionProxyReceiver.class)
|
||||
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
|
||||
.putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
|
||||
.putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
|
||||
.putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
|
||||
mSmartActionsEnabled)
|
||||
.setAction(Intent.ACTION_SEND)
|
||||
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
|
||||
UserHandle.SYSTEM);
|
||||
// cancel current pending intent (if any) since clipData isn't used for matching
|
||||
PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
|
||||
context, 0, sharingChooserIntent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
|
||||
transition.bundle, UserHandle.CURRENT);
|
||||
|
||||
Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
|
||||
Icon.createWithResource(r, R.drawable.ic_screenshot_share),
|
||||
r.getString(com.android.internal.R.string.share), shareAction);
|
||||
// Create a share action for the notification
|
||||
PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
|
||||
new Intent(context, ActionProxyReceiver.class)
|
||||
.putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
|
||||
.putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
|
||||
.putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
|
||||
.putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
|
||||
mSmartActionsEnabled)
|
||||
.setAction(Intent.ACTION_SEND)
|
||||
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
|
||||
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
|
||||
UserHandle.SYSTEM);
|
||||
|
||||
return shareActionBuilder.build();
|
||||
Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
|
||||
Icon.createWithResource(r, R.drawable.ic_screenshot_share),
|
||||
r.getString(com.android.internal.R.string.share), shareAction);
|
||||
|
||||
transition.shareAction = shareActionBuilder.build();
|
||||
return transition;
|
||||
};
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -354,8 +365,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
|
||||
if (!TextUtils.isEmpty(editorPackage)) {
|
||||
editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
|
||||
}
|
||||
editIntent.setType("image/png");
|
||||
editIntent.setData(uri);
|
||||
editIntent.setDataAndType(uri, "image/png");
|
||||
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
|
||||
@@ -34,6 +34,9 @@ import static java.util.Objects.requireNonNull;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ExitTransitionCoordinator;
|
||||
import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
|
||||
import android.app.Notification;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -46,6 +49,7 @@ import android.hardware.display.DisplayManager;
|
||||
import android.media.MediaActionSound;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -54,6 +58,7 @@ import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -67,15 +72,18 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.app.ChooserActivity;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.policy.PhoneWindow;
|
||||
import com.android.settingslib.applications.InterestingConfigChanges;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -103,17 +111,26 @@ public class ScreenshotController {
|
||||
*/
|
||||
static class SavedImageData {
|
||||
public Uri uri;
|
||||
public Notification.Action shareAction;
|
||||
public Supplier<ShareTransition> shareTransition;
|
||||
public Notification.Action editAction;
|
||||
public Notification.Action deleteAction;
|
||||
public List<Notification.Action> smartActions;
|
||||
|
||||
/**
|
||||
* POD for shared element transition to share sheet.
|
||||
*/
|
||||
static class ShareTransition {
|
||||
public Bundle bundle;
|
||||
public Notification.Action shareAction;
|
||||
public Runnable onCancelRunnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to reset the return data on error
|
||||
*/
|
||||
public void reset() {
|
||||
uri = null;
|
||||
shareAction = null;
|
||||
shareTransition = null;
|
||||
editAction = null;
|
||||
deleteAction = null;
|
||||
smartActions = null;
|
||||
@@ -587,7 +604,8 @@ public class ScreenshotController {
|
||||
mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
|
||||
}
|
||||
|
||||
mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
|
||||
mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
|
||||
getShareTransitionSupplier());
|
||||
mSaveInBgTask.execute();
|
||||
}
|
||||
|
||||
@@ -637,6 +655,35 @@ public class ScreenshotController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies the necessary bits for the shared element transition to share sheet.
|
||||
* Note that once supplied, the action intent to share must be sent immediately after.
|
||||
*/
|
||||
private Supplier<ShareTransition> getShareTransitionSupplier() {
|
||||
return () -> {
|
||||
ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
|
||||
@Override
|
||||
public boolean isReturnTransitionAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() { }
|
||||
};
|
||||
|
||||
Pair<ActivityOptions, ExitTransitionCoordinator> transition =
|
||||
ActivityOptions.startSharedElementAnimation(mWindow, cb, null,
|
||||
Pair.create(mScreenshotView.getScreenshotPreview(),
|
||||
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
|
||||
transition.second.startExit();
|
||||
|
||||
ShareTransition supply = new ShareTransition();
|
||||
supply.bundle = transition.first.toBundle();
|
||||
supply.onCancelRunnable = () -> ActivityOptions.stopSharedElementAnimation(mWindow);
|
||||
return supply;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs success/failure of the screenshot saving task, and shows an error if it failed.
|
||||
*/
|
||||
|
||||
@@ -73,6 +73,7 @@ import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -104,6 +105,7 @@ public class ScreenshotView extends FrameLayout implements
|
||||
private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
|
||||
private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
|
||||
private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
|
||||
private static final long SCREENSHOT_DISMISS_SHARE_OFFSET_MS = 300; // delay after share clicked
|
||||
private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
|
||||
private static final float ROUNDED_CORNER_RADIUS = .05f;
|
||||
private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
|
||||
@@ -138,6 +140,7 @@ public class ScreenshotView extends FrameLayout implements
|
||||
private UiEventLogger mUiEventLogger;
|
||||
private ScreenshotViewCallback mCallbacks;
|
||||
private Animator mDismissAnimation;
|
||||
private boolean mIgnoreDismiss;
|
||||
|
||||
private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
|
||||
private PendingInteraction mPendingInteraction;
|
||||
@@ -526,13 +529,31 @@ public class ScreenshotView extends FrameLayout implements
|
||||
});
|
||||
return animator;
|
||||
}
|
||||
protected View getScreenshotPreview() {
|
||||
return mScreenshotPreview;
|
||||
}
|
||||
|
||||
void setChipIntents(ScreenshotController.SavedImageData imageData) {
|
||||
mShareChip.setPendingIntent(imageData.shareAction.actionIntent,
|
||||
() -> {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
|
||||
mShareChip.setOnClickListener(v -> {
|
||||
ShareTransition transition = imageData.shareTransition.get();
|
||||
try {
|
||||
mIgnoreDismiss = true;
|
||||
transition.shareAction.actionIntent.send();
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
|
||||
|
||||
// Ensures that we delay dismissing until transition has started.
|
||||
postDelayed(() -> {
|
||||
mIgnoreDismiss = false;
|
||||
animateDismissal();
|
||||
});
|
||||
}, SCREENSHOT_DISMISS_SHARE_OFFSET_MS);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
mIgnoreDismiss = false;
|
||||
if (transition.onCancelRunnable != null) {
|
||||
transition.onCancelRunnable.run();
|
||||
}
|
||||
Log.e(TAG, "Share intent cancelled", e);
|
||||
}
|
||||
});
|
||||
mEditChip.setPendingIntent(imageData.editAction.actionIntent,
|
||||
() -> {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED);
|
||||
@@ -589,6 +610,9 @@ public class ScreenshotView extends FrameLayout implements
|
||||
}
|
||||
|
||||
private void animateDismissal(Animator dismissAnimation) {
|
||||
if (mIgnoreDismiss) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG_WINDOW) {
|
||||
Log.d(TAG, "removing OnComputeInternalInsetsListener");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SystemUIFactory;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -175,10 +176,11 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
|
||||
data.finisher = null;
|
||||
data.mActionsReadyListener = null;
|
||||
SaveImageInBackgroundTask task =
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
|
||||
ShareTransition::new);
|
||||
|
||||
Notification.Action shareAction = task.createShareAction(mContext, mContext.getResources(),
|
||||
Uri.parse("Screenshot_123.png"));
|
||||
Uri.parse("Screenshot_123.png")).get().shareAction;
|
||||
|
||||
Intent intent = shareAction.actionIntent.getIntent();
|
||||
assertNotNull(intent);
|
||||
@@ -202,7 +204,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
|
||||
data.finisher = null;
|
||||
data.mActionsReadyListener = null;
|
||||
SaveImageInBackgroundTask task =
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
|
||||
ShareTransition::new);
|
||||
|
||||
Notification.Action editAction = task.createEditAction(mContext, mContext.getResources(),
|
||||
Uri.parse("Screenshot_123.png"));
|
||||
@@ -229,7 +232,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
|
||||
data.finisher = null;
|
||||
data.mActionsReadyListener = null;
|
||||
SaveImageInBackgroundTask task =
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
|
||||
new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
|
||||
ShareTransition::new);
|
||||
|
||||
Notification.Action deleteAction = task.createDeleteAction(mContext,
|
||||
mContext.getResources(),
|
||||
|
||||
Reference in New Issue
Block a user