import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
-import com.android.camera.device.ActiveCameraDeviceTracker;
import com.android.camera.device.CameraId;
import com.android.camera.hardware.HardwareSpec;
import com.android.camera.hardware.HeadingSensor;
package com.android.camera.captureintent;
-import com.android.camera.app.MediaSaver;
+import android.graphics.Bitmap;
+import android.location.Location;
+import android.net.Uri;
+
import com.android.camera.debug.Log;
import com.android.camera.exif.ExifInterface;
import com.android.camera.session.CaptureSession;
import com.android.camera.session.TemporarySessionFile;
import com.android.camera.stats.CaptureSessionStatsCollector;
import com.android.camera.util.Size;
-
-import android.graphics.Bitmap;
-import android.location.Location;
-import android.net.Uri;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
/**
* An implementation of {@link CaptureSession} which is used by
}
@Override
- public synchronized void saveAndFinish(byte[] data, int width, int height, int orientation,
- ExifInterface exif, final MediaSaver.OnMediaSavedListener listener) {
+ public synchronized ListenableFuture<Optional<Uri>> saveAndFinish(byte[] data, int width,
+ int height, int orientation, ExifInterface exif) {
mSessionNotifier.notifySessionPictureDataAvailable(data, orientation);
+ return Futures.immediateFuture(Optional.<Uri> absent());
}
@Override
import com.android.camera.CaptureModuleUtil;
import com.android.camera.Exif;
import com.android.camera.Storage;
-import com.android.camera.app.MediaSaver.OnMediaSavedListener;
import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
import com.android.camera.util.JpegUtilNative;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.io.File;
import java.io.FileOutputStream;
Log.w(TAG, "Could not read exif from gcam jpeg", e);
exif = null;
}
- session.saveAndFinish(jpegData, width, height, rotation, exif, new OnMediaSavedListener() {
+ ListenableFuture<Optional<Uri>> futureUri = session.saveAndFinish(jpegData, width, height,
+ rotation, exif);
+ Futures.addCallback(futureUri, new FutureCallback<Optional<Uri>>() {
@Override
- public void onMediaSaved(Uri uri) {
- captureParams.callback.onPictureSaved(uri);
+ public void onSuccess(Optional<Uri> uriOptional) {
+ captureParams.callback.onPictureSaved(uriOptional.orNull());
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ captureParams.callback.onPictureSaved(null);
}
});
}
import android.view.Surface;
import com.android.camera.CaptureModuleUtil;
-import com.android.camera.app.MediaSaver.OnMediaSavedListener;
import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
import com.android.camera.exif.ExifInterface;
import com.android.camera.util.ListenerCombiner;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.nio.ByteBuffer;
import java.security.InvalidParameterException;
new ExifUtil(exif).populateExif(Optional.<TaskImageContainer.TaskImage>absent(),
Optional.of((CaptureResultProxy) new AndroidCaptureResultProxy(result)),
Optional.<Location>absent());
- session.saveAndFinish(acquireJpegBytes(image, degrees),
- size.getWidth(), size.getHeight(), 0, exif, new OnMediaSavedListener() {
- @Override
- public void onMediaSaved(Uri uri) {
- captureParams.callback.onPictureSaved(uri);
- }
- });
+ ListenableFuture<Optional<Uri>> futureUri = session.saveAndFinish(
+ acquireJpegBytes(image, degrees),
+ size.getWidth(), size.getHeight(), 0, exif);
+ Futures.addCallback(futureUri, new FutureCallback<Optional<Uri>>() {
+ @Override
+ public void onSuccess(Optional<Uri> uriOptional) {
+ captureParams.callback.onPictureSaved(uriOptional.orNull());
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ captureParams.callback.onPictureSaved(null);
+ }
+ });
}
/**
import android.net.Uri;
import com.android.camera.Exif;
-import com.android.camera.app.MediaSaver;
import com.android.camera.app.OrientationManager.DeviceOrientation;
-import com.android.camera.async.Listenable;
import com.android.camera.debug.Log;
import com.android.camera.exif.ExifInterface;
import com.android.camera.one.v2.camera2proxy.CaptureResultProxy;
import com.android.camera.util.JpegUtilNative;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.nio.ByteBuffer;
final ExifInterface exif = createExif(Optional.fromNullable(exifData), resultImage,
img.metadata);
mSession.getCollector().decorateAtTimeWriteToDisk(exif);
- mSession.saveAndFinish(writeOut, resultImage.width, resultImage.height,
- resultImage.orientation.getDegrees(), exif,
- new MediaSaver.OnMediaSavedListener() {
- @Override
- public void onMediaSaved(Uri uri) {
- onUriResolved(mId, finalInput, finalResult, uri,
- TaskInfo.Destination.FINAL_IMAGE);
- }
- });
+ ListenableFuture<Optional<Uri>> futureUri = mSession.saveAndFinish(writeOut,
+ resultImage.width, resultImage.height, resultImage.orientation.getDegrees(), exif);
+ Futures.addCallback(futureUri, new FutureCallback<Optional<Uri>>() {
+ @Override
+ public void onSuccess(Optional<Uri> uriOptional) {
+ if (uriOptional.isPresent()) {
+ onUriResolved(mId, finalInput, finalResult, uriOptional.get(),
+ TaskInfo.Destination.FINAL_IMAGE);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ }
+ });
final ListenableFuture<TotalCaptureResultProxy> requestMetadata = img.metadata;
// If TotalCaptureResults are available add them to the capture event.
import android.location.Location;
import android.net.Uri;
-import com.android.camera.app.MediaSaver.OnMediaSavedListener;
import com.android.camera.exif.ExifInterface;
import com.android.camera.stats.CaptureSessionStatsCollector;
import com.android.camera.util.Size;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
/**
* A session is an item that is in progress of being created and saved, such as
/**
* Finish the session by saving the image to disk. Will add the final item
* in the film strip and remove the progress notifications.
- */
- public void saveAndFinish(byte[] data, int width, int height, int orientation,
- ExifInterface exif, OnMediaSavedListener listener);
+ *
+ * @param data the data of the data (e.g. JPEG bytes) that should be written
+ * to disk.
+ * @param width the width of the media item, in pixels.
+ * @param height the height of the media item, in pixels.
+ * @param orientation the orientaiton of the media item, in degrees.
+ * @param exif the EXIF information for this media item.
+ * @return A future that will provide the URI once the item is saved. URI
+ * might be absent if the data could not be saved successfull, which
+ * in turn means if a URI is returned it is guaranteed that the
+ * media item was successfully written to disk.
+ */
+ public ListenableFuture<Optional<Uri>> saveAndFinish(byte[] data, int width, int height,
+ int orientation, ExifInterface exif);
/**
* Will create and return a {@link StackSaver} for saving out a number of
import com.android.camera.util.FileUtil;
import com.android.camera.util.Size;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
import java.io.File;
import java.io.IOException;
}
@Override
- public synchronized void saveAndFinish(byte[] data, int width, int height, int orientation,
- ExifInterface exif, final MediaSaver.OnMediaSavedListener listener) {
+ public synchronized ListenableFuture<Optional<Uri>> saveAndFinish(byte[] data, int width, int height,
+ int orientation, ExifInterface exif) {
+ final SettableFuture<Optional<Uri>> futureResult = SettableFuture.create();
+
mIsFinished = true;
if (mPlaceHolderSession == null) {
mMediaSaver.addImage(
data, mTitle, mSessionStartMillis, mLocation, width, height,
- orientation, exif, listener);
- return;
- }
- try {
- mContentUri = mPlaceholderManager.finishPlaceholder(mPlaceHolderSession, mLocation,
- orientation, exif, data, width, height, FilmstripItemData.MIME_TYPE_JPEG);
- mSessionNotifier.notifyTaskDone(mUri);
- } catch (IOException e) {
- Log.e(TAG, "IOException", e);
- // TODO: Replace with a sensisble description
- // Placeholder string R.string.reason_storage_failure
- finishWithFailure(-1, true);
+ orientation, exif, new MediaSaver.OnMediaSavedListener() {
+ @Override
+ public void onMediaSaved(Uri uri) {
+ futureResult.set(Optional.fromNullable(uri));
+ }
+ });
+ } else {
+ try {
+ mContentUri = mPlaceholderManager.finishPlaceholder(mPlaceHolderSession, mLocation,
+ orientation, exif, data, width, height, FilmstripItemData.MIME_TYPE_JPEG);
+ mSessionNotifier.notifyTaskDone(mUri);
+ futureResult.set(Optional.fromNullable(mUri));
+ } catch (IOException e) {
+ Log.e(TAG, "Could not write file", e);
+ finishWithFailure(-1, true);
+ futureResult.setException(e);
+ }
}
+ return futureResult;
}
@Override
Log.w(TAG, "Could not read exif", e);
exif = null;
}
- CaptureSessionImpl.this.saveAndFinish(jpegData, width, height, rotation, exif,
- null);
+ CaptureSessionImpl.this.saveAndFinish(jpegData, width, height, rotation, exif);
}
});