Merge "Move long screenshot UI to an Activity" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3a8a885261
@@ -334,6 +334,11 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity android:name=".screenshot.LongScreenshotActivity"
|
||||
android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
|
||||
android:process=":screenshot"
|
||||
android:finishOnTaskLaunch="true" />
|
||||
|
||||
<activity android:name=".screenrecord.ScreenRecordDialog"
|
||||
android:theme="@style/ScreenRecord"
|
||||
android:showForAllUsers="true"
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.systemui.ForegroundServicesDialog;
|
||||
import com.android.systemui.keyguard.WorkLockActivity;
|
||||
import com.android.systemui.people.PeopleSpaceActivity;
|
||||
import com.android.systemui.screenrecord.ScreenRecordDialog;
|
||||
import com.android.systemui.screenshot.LongScreenshotActivity;
|
||||
import com.android.systemui.settings.brightness.BrightnessDialog;
|
||||
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
|
||||
import com.android.systemui.tuner.TunerActivity;
|
||||
@@ -99,4 +100,10 @@ public abstract class DefaultActivityBinder {
|
||||
@IntoMap
|
||||
@ClassKey(PeopleSpaceActivity.class)
|
||||
public abstract Activity bindPeopleSpaceActivity(PeopleSpaceActivity activity);
|
||||
|
||||
/** Inject into LongScreenshotActivity. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(LongScreenshotActivity.class)
|
||||
public abstract Activity bindLongScreenshotActivity(LongScreenshotActivity activity);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.screenshot;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* LongScreenshotActivity acquires bitmap data for a long screenshot and lets the user trim the top
|
||||
* and bottom before saving/sharing/editing.
|
||||
*/
|
||||
public class LongScreenshotActivity extends Activity {
|
||||
private static final String TAG = "LongScreenshotActivity";
|
||||
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final ScrollCaptureController mScrollCaptureController;
|
||||
|
||||
private ImageView mPreview;
|
||||
private View mSave;
|
||||
private View mCancel;
|
||||
private View mEdit;
|
||||
private View mShare;
|
||||
private CropView mCropView;
|
||||
private MagnifierView mMagnifierView;
|
||||
|
||||
private enum PendingAction {
|
||||
SHARE,
|
||||
EDIT,
|
||||
SAVE
|
||||
}
|
||||
|
||||
@Inject
|
||||
public LongScreenshotActivity(UiEventLogger uiEventLogger,
|
||||
ImageExporter imageExporter,
|
||||
@Main Executor mainExecutor,
|
||||
@Background Executor bgExecutor,
|
||||
Context context) {
|
||||
mUiEventLogger = uiEventLogger;
|
||||
|
||||
mScrollCaptureController = new ScrollCaptureController(context,
|
||||
ScreenshotController.sScrollConnection, mainExecutor, bgExecutor, imageExporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.long_screenshot);
|
||||
|
||||
mPreview = findViewById(R.id.preview);
|
||||
mSave = findViewById(R.id.save);
|
||||
mCancel = findViewById(R.id.cancel);
|
||||
mEdit = findViewById(R.id.edit);
|
||||
mShare = findViewById(R.id.share);
|
||||
mCropView = findViewById(R.id.crop_view);
|
||||
mMagnifierView = findViewById(R.id.magnifier);
|
||||
mCropView.setCropInteractionListener(mMagnifierView);
|
||||
|
||||
mSave.setOnClickListener(this::onClicked);
|
||||
mCancel.setOnClickListener(this::onClicked);
|
||||
mEdit.setOnClickListener(this::onClicked);
|
||||
mShare.setOnClickListener(this::onClicked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (mPreview.getDrawable() == null) {
|
||||
doCapture();
|
||||
}
|
||||
}
|
||||
|
||||
private void disableButtons() {
|
||||
mSave.setEnabled(false);
|
||||
mCancel.setEnabled(false);
|
||||
mEdit.setEnabled(false);
|
||||
mShare.setEnabled(false);
|
||||
}
|
||||
|
||||
private void doEdit(Uri uri) {
|
||||
String editorPackage = getString(R.string.config_screenshotEditor);
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
if (!TextUtils.isEmpty(editorPackage)) {
|
||||
intent.setComponent(ComponentName.unflattenFromString(editorPackage));
|
||||
}
|
||||
intent.setType("image/png");
|
||||
intent.setData(uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
finishAndRemoveTask();
|
||||
}
|
||||
|
||||
private void doShare(Uri uri) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/png");
|
||||
intent.setData(uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
Intent sharingChooserIntent = Intent.createChooser(intent, null)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
private void onClicked(View v) {
|
||||
int id = v.getId();
|
||||
v.setPressed(true);
|
||||
disableButtons();
|
||||
if (id == R.id.save) {
|
||||
startExport(PendingAction.SAVE);
|
||||
} else if (id == R.id.cancel) {
|
||||
finishAndRemoveTask();
|
||||
} else if (id == R.id.edit) {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
|
||||
startExport(PendingAction.EDIT);
|
||||
} else if (id == R.id.share) {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
|
||||
startExport(PendingAction.SHARE);
|
||||
}
|
||||
}
|
||||
|
||||
private void startExport(PendingAction action) {
|
||||
mScrollCaptureController.startExport(mCropView.getTopBoundary(),
|
||||
mCropView.getBottomBoundary(), new ScrollCaptureController.ExportCallback() {
|
||||
@Override
|
||||
public void onError() {
|
||||
Log.e(TAG, "Error exporting image data.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExportComplete(Uri outputUri) {
|
||||
switch (action) {
|
||||
case EDIT:
|
||||
doEdit(outputUri);
|
||||
break;
|
||||
case SHARE:
|
||||
doShare(outputUri);
|
||||
break;
|
||||
case SAVE:
|
||||
// Nothing more to do
|
||||
finishAndRemoveTask();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doCapture() {
|
||||
mScrollCaptureController.start(new ScrollCaptureController.ScrollCaptureCallback() {
|
||||
@Override
|
||||
public void onError() {
|
||||
Log.e(TAG, "Error!");
|
||||
finishAndRemoveTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(ImageTileSet imageTileSet) {
|
||||
Log.i(TAG, "Got tiles " + imageTileSet.getWidth() + " x "
|
||||
+ imageTileSet.getHeight());
|
||||
mPreview.setImageDrawable(imageTileSet.getDrawable());
|
||||
mMagnifierView.setImageTileset(imageTileSet);
|
||||
mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ import android.app.Notification;
|
||||
import android.app.WindowContext;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
@@ -100,6 +101,8 @@ import javax.inject.Inject;
|
||||
public class ScreenshotController {
|
||||
private static final String TAG = logTag(ScreenshotController.class);
|
||||
|
||||
public static ScrollCaptureClient.Connection sScrollConnection;
|
||||
|
||||
/**
|
||||
* POD used in the AsyncTask which saves an image in the background.
|
||||
*/
|
||||
@@ -597,21 +600,12 @@ public class ScreenshotController {
|
||||
}
|
||||
|
||||
private void runScrollCapture(ScrollCaptureClient.Connection connection) {
|
||||
cancelTimeout();
|
||||
ScrollCaptureController controller = new ScrollCaptureController(mContext, connection,
|
||||
mMainExecutor, mBgExecutor, mImageExporter, mUiEventLogger);
|
||||
controller.attach(mWindow);
|
||||
controller.start(new TakeScreenshotService.RequestCallback() {
|
||||
@Override
|
||||
public void reportError() {
|
||||
}
|
||||
sScrollConnection = connection; // For LongScreenshotActivity to pick up.
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
Log.d(TAG, "onFinish from ScrollCaptureController");
|
||||
finishDismiss();
|
||||
}
|
||||
});
|
||||
Intent intent = new Intent(mContext, LongScreenshotActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
mContext.startActivity(intent);
|
||||
dismissScreenshot(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,29 +16,16 @@
|
||||
|
||||
package com.android.systemui.screenshot;
|
||||
|
||||
import android.annotation.IdRes;
|
||||
import android.annotation.UiThread;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver.InternalInsetsInfo;
|
||||
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.screenshot.ScrollCaptureClient.CaptureResult;
|
||||
import com.android.systemui.screenshot.ScrollCaptureClient.Connection;
|
||||
import com.android.systemui.screenshot.ScrollCaptureClient.Session;
|
||||
import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
@@ -50,7 +37,7 @@ import java.util.concurrent.Executor;
|
||||
/**
|
||||
* Interaction controller between the UI and ScrollCaptureClient.
|
||||
*/
|
||||
public class ScrollCaptureController implements OnComputeInternalInsetsListener {
|
||||
public class ScrollCaptureController {
|
||||
private static final String TAG = "ScrollCaptureController";
|
||||
private static final float MAX_PAGES_DEFAULT = 3f;
|
||||
|
||||
@@ -64,13 +51,6 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
|
||||
private boolean mAtTopEdge;
|
||||
private Session mSession;
|
||||
|
||||
// TODO: Support saving without additional action.
|
||||
private enum PendingAction {
|
||||
SHARE,
|
||||
EDIT,
|
||||
SAVE
|
||||
}
|
||||
|
||||
public static final int MAX_HEIGHT = 12000;
|
||||
|
||||
private final Connection mConnection;
|
||||
@@ -80,172 +60,59 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
|
||||
private final Executor mBgExecutor;
|
||||
private final ImageExporter mImageExporter;
|
||||
private final ImageTileSet mImageTileSet;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
private ZonedDateTime mCaptureTime;
|
||||
private UUID mRequestId;
|
||||
private RequestCallback mCallback;
|
||||
private Window mWindow;
|
||||
private ImageView mPreview;
|
||||
private View mSave;
|
||||
private View mCancel;
|
||||
private View mEdit;
|
||||
private View mShare;
|
||||
private CropView mCropView;
|
||||
private MagnifierView mMagnifierView;
|
||||
private ScrollCaptureCallback mCaptureCallback;
|
||||
|
||||
public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor,
|
||||
Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) {
|
||||
Executor bgExecutor, ImageExporter exporter) {
|
||||
mContext = context;
|
||||
mConnection = connection;
|
||||
mUiExecutor = uiExecutor;
|
||||
mBgExecutor = bgExecutor;
|
||||
mImageExporter = exporter;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mImageTileSet = new ImageTileSet(context.getMainThreadHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param window the window to display the preview
|
||||
*/
|
||||
public void attach(Window window) {
|
||||
mWindow = window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run scroll capture!
|
||||
*
|
||||
* @param callback request callback to report back to the service
|
||||
*/
|
||||
public void start(RequestCallback callback) {
|
||||
public void start(ScrollCaptureCallback callback) {
|
||||
mCaptureTime = ZonedDateTime.now();
|
||||
mRequestId = UUID.randomUUID();
|
||||
mCallback = callback;
|
||||
|
||||
setContentView(R.layout.long_screenshot);
|
||||
mWindow.getDecorView().getViewTreeObserver()
|
||||
.addOnComputeInternalInsetsListener(this);
|
||||
mPreview = findViewById(R.id.preview);
|
||||
|
||||
mSave = findViewById(R.id.save);
|
||||
mCancel = findViewById(R.id.cancel);
|
||||
mEdit = findViewById(R.id.edit);
|
||||
mShare = findViewById(R.id.share);
|
||||
mCropView = findViewById(R.id.crop_view);
|
||||
mMagnifierView = findViewById(R.id.magnifier);
|
||||
mCropView.setCropInteractionListener(mMagnifierView);
|
||||
|
||||
mSave.setOnClickListener(this::onClicked);
|
||||
mCancel.setOnClickListener(this::onClicked);
|
||||
mEdit.setOnClickListener(this::onClicked);
|
||||
mShare.setOnClickListener(this::onClicked);
|
||||
mCaptureCallback = callback;
|
||||
|
||||
float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
|
||||
SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
|
||||
mConnection.start(this::startCapture, maxPages);
|
||||
}
|
||||
|
||||
|
||||
/** Ensure the entire window is touchable */
|
||||
public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
|
||||
inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
|
||||
}
|
||||
|
||||
void disableButtons() {
|
||||
mSave.setEnabled(false);
|
||||
mCancel.setEnabled(false);
|
||||
mEdit.setEnabled(false);
|
||||
mShare.setEnabled(false);
|
||||
}
|
||||
|
||||
private void onClicked(View v) {
|
||||
Log.d(TAG, "button clicked!");
|
||||
|
||||
int id = v.getId();
|
||||
v.setPressed(true);
|
||||
disableButtons();
|
||||
if (id == R.id.save) {
|
||||
startExport(PendingAction.SAVE);
|
||||
} else if (id == R.id.cancel) {
|
||||
doFinish();
|
||||
} else if (id == R.id.edit) {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
|
||||
startExport(PendingAction.EDIT);
|
||||
} else if (id == R.id.share) {
|
||||
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
|
||||
startExport(PendingAction.SHARE);
|
||||
}
|
||||
}
|
||||
|
||||
private void doFinish() {
|
||||
mPreview.setImageDrawable(null);
|
||||
mMagnifierView.setImageTileset(null);
|
||||
mImageTileSet.clear();
|
||||
mCallback.onFinish();
|
||||
mWindow.getDecorView().getViewTreeObserver()
|
||||
.removeOnComputeInternalInsetsListener(this);
|
||||
}
|
||||
|
||||
private void startExport(PendingAction action) {
|
||||
/**
|
||||
* @param topCrop [0,1) fraction of the top of the image to be cropped out.
|
||||
* @param bottomCrop (0, 1] fraction to be cropped out, e.g. 0.7 will crop out the bottom 30%.
|
||||
*/
|
||||
public void startExport(float topCrop, float bottomCrop, ExportCallback callback) {
|
||||
Rect croppedPortion = new Rect(
|
||||
0,
|
||||
(int) (mImageTileSet.getHeight() * mCropView.getTopBoundary()),
|
||||
(int) (mImageTileSet.getHeight() * topCrop),
|
||||
mImageTileSet.getWidth(),
|
||||
(int) (mImageTileSet.getHeight() * mCropView.getBottomBoundary()));
|
||||
(int) (mImageTileSet.getHeight() * bottomCrop));
|
||||
ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
|
||||
mBgExecutor, mRequestId, mImageTileSet.toBitmap(croppedPortion), mCaptureTime);
|
||||
exportFuture.addListener(() -> {
|
||||
try {
|
||||
ImageExporter.Result result = exportFuture.get();
|
||||
if (action == PendingAction.EDIT) {
|
||||
doEdit(result.uri);
|
||||
} else if (action == PendingAction.SHARE) {
|
||||
doShare(result.uri);
|
||||
}
|
||||
doFinish();
|
||||
callback.onExportComplete(result.uri);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
Log.e(TAG, "failed to export", e);
|
||||
mCallback.onFinish();
|
||||
callback.onError();
|
||||
}
|
||||
}, mUiExecutor);
|
||||
}
|
||||
|
||||
private void doEdit(Uri uri) {
|
||||
String editorPackage = mContext.getString(R.string.config_screenshotEditor);
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
if (!TextUtils.isEmpty(editorPackage)) {
|
||||
intent.setComponent(ComponentName.unflattenFromString(editorPackage));
|
||||
}
|
||||
intent.setType("image/png");
|
||||
intent.setData(uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
private void doShare(Uri uri) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/png");
|
||||
intent.setData(uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
Intent sharingChooserIntent = Intent.createChooser(intent, null)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
mContext.startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
private void setContentView(@IdRes int id) {
|
||||
mWindow.setContentView(id);
|
||||
}
|
||||
|
||||
<T extends View> T findViewById(@IdRes int res) {
|
||||
return mWindow.findViewById(res);
|
||||
}
|
||||
|
||||
|
||||
private void onCaptureResult(CaptureResult result) {
|
||||
Log.d(TAG, "onCaptureResult: " + result);
|
||||
boolean emptyResult = result.captured.height() == 0;
|
||||
@@ -327,11 +194,26 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
|
||||
Log.d(TAG, "afterCaptureComplete");
|
||||
|
||||
if (mImageTileSet.isEmpty()) {
|
||||
session.end(mCallback::onFinish);
|
||||
mCaptureCallback.onError();
|
||||
} else {
|
||||
mPreview.setImageDrawable(mImageTileSet.getDrawable());
|
||||
mMagnifierView.setImageTileset(mImageTileSet);
|
||||
mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
|
||||
mCaptureCallback.onComplete(mImageTileSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for image capture completion or error.
|
||||
*/
|
||||
public interface ScrollCaptureCallback {
|
||||
void onComplete(ImageTileSet imageTileSet);
|
||||
void onError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for image export completion or error.
|
||||
*/
|
||||
public interface ExportCallback {
|
||||
void onExportComplete(Uri outputUri);
|
||||
void onError();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user