diff options
Diffstat (limited to 'src')
8 files changed, 321 insertions, 74 deletions
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 49b209d34..7c4487b90 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -49,7 +49,6 @@ import android.os.SystemClock; import android.provider.MediaStore; import android.util.Log; import android.view.KeyEvent; -import android.view.MotionEvent; import android.view.OrientationEventListener; import android.view.SurfaceHolder; import android.view.View; @@ -74,7 +73,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Collections; import java.util.Formatter; import java.util.List; @@ -940,18 +938,16 @@ public class PhotoModule } private void animateFlash() { - /* //TODO: // Only animate when in full screen capture mode // i.e. If monkey/a user swipes to the gallery during picture taking, // don't show animation - if (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent - && mActivity.mShowCameraAppView) { - // Start capture animation. - ((CameraScreenNail) mActivity.mCameraScreenNail).animateFlash(mDisplayRotation); - mUI.enablePreviewThumb(true); - mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE, - CaptureAnimManager.getAnimationDuration()); - } */ + if (!mIsImageCaptureIntent) { + mUI.animateFlash(); + + // TODO: mUI.enablePreviewThumb(true); + // mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE, + // CaptureAnimManager.getAnimationDuration()); + } } @Override diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 1468a3ce4..b2a9df8cc 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -17,6 +17,9 @@ package com.android.camera; +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.Camera; @@ -108,6 +111,8 @@ public class PhotoUI implements PieListener, private float mSurfaceTextureUncroppedHeight; private View mPreviewThumb; + private ObjectAnimator mFlashAnim; + private View mFlashOverlay; private SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener; private TextureView mTextureView; @@ -153,6 +158,26 @@ public class PhotoUI implements PieListener, } }; + private ValueAnimator.AnimatorListener mAnimatorListener = + new ValueAnimator.AnimatorListener() { + + @Override + public void onAnimationCancel(Animator arg0) {} + + @Override + public void onAnimationEnd(Animator arg0) { + mFlashOverlay.setAlpha(0f); + mFlashOverlay.setVisibility(View.GONE); + mFlashAnim.removeListener(this); + } + + @Override + public void onAnimationRepeat(Animator arg0) {} + + @Override + public void onAnimationStart(Animator arg0) {} + }; + public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { mActivity = activity; mController = controller; @@ -161,6 +186,7 @@ public class PhotoUI implements PieListener, mActivity.getLayoutInflater().inflate(R.layout.photo_module, (ViewGroup) mRootView, true); mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); + mFlashOverlay = mRootView.findViewById(R.id.flash_overlay); // display the view mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content); mTextureView.setSurfaceTextureListener(this); @@ -444,6 +470,19 @@ public class PhotoUI implements PieListener, public void setCameraState(int state) { } + public void animateFlash() { + // End the previous animation if the previous one is still running + if (mFlashAnim != null && mFlashAnim.isRunning()) { + mFlashAnim.end(); + } + // Start new flash animation. + mFlashOverlay.setVisibility(View.VISIBLE); + mFlashAnim = ObjectAnimator.ofFloat((Object) mFlashOverlay, "alpha", 0.3f, 0f); + mFlashAnim.setDuration(300); + mFlashAnim.addListener(mAnimatorListener); + mFlashAnim.start(); + } + public void enableGestures(boolean enable) { if (mGestures != null) { mGestures.setEnabled(enable); diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java index 1ed67ecf4..a7c98af77 100644 --- a/src/com/android/gallery3d/data/LocalImage.java +++ b/src/com/android/gallery3d/data/LocalImage.java @@ -35,9 +35,9 @@ import com.android.gallery3d.app.PanoramaMetadataSupport; import com.android.gallery3d.app.StitchingProgressManager; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.exif.ExifTag; +import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.util.GalleryUtils; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; @@ -46,8 +46,6 @@ import com.android.gallery3d.util.UpdateHelper; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel.MapMode; // LocalImage represents an image in the local storage. public class LocalImage extends LocalMediaItem { @@ -271,7 +269,9 @@ public class LocalImage extends LocalMediaItem { public void delete() { GalleryUtils.assertNotInRenderThread(); Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - mApplication.getContentResolver().delete(baseUri, "_id=?", + ContentResolver contentResolver = mApplication.getContentResolver(); + SaveCopyTask.deleteAuxFiles(contentResolver, getContentUri()); + contentResolver.delete(baseUri, "_id=?", new String[]{String.valueOf(id)}); } diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 7ba0fcc9c..289a4c37b 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -138,6 +138,8 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL private Uri mOriginalImageUri = null; private ImagePreset mOriginalPreset = null; + private Uri mSelectedImageUri = null; + private CategoryAdapter mCategoryLooksAdapter = null; private CategoryAdapter mCategoryBordersAdapter = null; private CategoryAdapter mCategoryGeometryAdapter = null; @@ -310,12 +312,13 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL } mAction = intent.getAction(); - Uri srcUri = intent.getData(); + mSelectedImageUri = intent.getData(); + Uri loadUri = mSelectedImageUri; if (mOriginalImageUri != null) { - srcUri = mOriginalImageUri; + loadUri = mOriginalImageUri; } - if (srcUri != null) { - startLoadBitmap(srcUri); + if (loadUri != null) { + startLoadBitmap(loadUri); } else { pickImage(); } @@ -925,11 +928,13 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit); builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int id) { saveImage(); } }); builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() { + @Override public void onClick(DialogInterface dialog, int id) { done(); } @@ -983,7 +988,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL public void saveImage() { if (mImageShow.hasModifications()) { // Get the name of the album, to which the image will be saved - File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri()); + File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mSelectedImageUri); int bucketId = GalleryUtils.getBucketId(saveDir.getPath()); String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null); showSavingProgress(albumName); @@ -1002,10 +1007,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL finish(); } - static { - System.loadLibrary("jni_filtershow_filters"); - } - private void extractXMPData() { XMresults res = XmpPresets.extractXMPData( getBaseContext(), mMasterImage, getIntent().getData()); @@ -1015,4 +1016,14 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL mOriginalImageUri = res.originalimage; mOriginalPreset = res.preset; } + + public Uri getSelectedImageUri() { + return mSelectedImageUri; + } + + static { + System.loadLibrary("jni_filtershow_filters"); + } + + } diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index 7ddd9bebe..491340e0d 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -394,7 +394,9 @@ public class ImageLoader { public void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, File destination) { - new SaveCopyTask(mContext, mUri, destination, new SaveCopyTask.Callback() { + Uri selectedImageUri = filterShowActivity.getSelectedImageUri(); + new SaveCopyTask(mContext, mUri, selectedImageUri, destination, + new SaveCopyTask.Callback() { @Override public void onComplete(Uri result) { diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java index dfe0308c1..abe69d110 100644 --- a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java +++ b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java @@ -56,6 +56,7 @@ public class FilterFxRepresentation extends FilterRepresentation { if (a instanceof FilterFxRepresentation) { FilterFxRepresentation representation = (FilterFxRepresentation) a; setName(representation.getName()); + setSerializationName(representation.getSerializationName()); setBitmapResource(representation.getBitmapResource()); setNameResource(representation.getNameResource()); } diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java index 1d8ab07a1..9e96e96c3 100644 --- a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java +++ b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java @@ -25,6 +25,7 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Environment; +import android.provider.MediaStore; import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; @@ -40,6 +41,7 @@ import com.android.gallery3d.util.XmpUtilHelper; import java.io.File; import java.io.FileNotFoundException; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.sql.Date; @@ -61,7 +63,7 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { void onComplete(Uri result); } - private interface ContentResolverQueryCallback { + public interface ContentResolverQueryCallback { void onCursorResult(Cursor cursor); } @@ -70,26 +72,68 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { private static final String PREFIX_PANO = "PANO"; private static final String PREFIX_IMG = "IMG"; private static final String POSTFIX_JPG = ".jpg"; + private static final String AUX_DIR_NAME = ".aux"; + + private final Context mContext; + private final Uri mSourceUri; + private final Callback mCallback; + private final File mDestinationFile; + private final Uri mSelectedImageUri; + + // In order to support the new edit-save behavior such that user won't see + // the edited image together with the original image, we are adding a new + // auxiliary directory for the edited image. Basically, the original image + // will be hidden in that directory after edit and user will see the edited + // image only. + // Note that deletion on the edited image will also cause the deletion of + // the original image under auxiliary directory. + // + // There are several situations we need to consider: + // 1. User edit local image local01.jpg. A local02.jpg will be created in the + // same directory, and original image will be moved to auxiliary directory as + // ./.aux/local02.jpg. + // If user edit the local02.jpg, local03.jpg will be created in the local + // directory and ./.aux/local02.jpg will be renamed to ./.aux/local03.jpg + // + // 2. User edit remote image remote01.jpg from picassa or other server. + // remoteSavedLocal01.jpg will be saved under proper local directory. + // In remoteSavedLocal01.jpg, there will be a reference pointing to the + // remote01.jpg. There will be no local copy of remote01.jpg. + // If user edit remoteSavedLocal01.jpg, then a new remoteSavedLocal02.jpg + // will be generated and still pointing to the remote01.jpg + // + // 3. User delete any local image local.jpg. + // Since the filenames are kept consistent in auxiliary directory, every + // time a local.jpg get deleted, the files in auxiliary directory whose + // names starting with "local." will be deleted. + // This pattern will facilitate the multiple images deletion in the auxiliary + // directory. + // + // TODO: Move the saving into a background service. - private final Context context; - private final Uri sourceUri; - private final Callback callback; - private final String saveFileName; - private final File destinationFile; - - public SaveCopyTask(Context context, Uri sourceUri, File destination, Callback callback) { - this.context = context; - this.sourceUri = sourceUri; - this.callback = callback; - + /** + * @param context + * @param sourceUri The Uri for the original image, which can be the hidden + * image under the auxiliary directory or the same as selectedImageUri. + * @param selectedImageUri The Uri for the image selected by the user. + * In most cases, it is a content Uri for local image or remote image. + * @param destination Destinaton File, if this is null, a new file will be + * created under the same directory as selectedImageUri. + * @param callback Let the caller know the saving has completed. + * @return the newSourceUri + */ + public SaveCopyTask(Context context, Uri sourceUri, Uri selectedImageUri, + File destination, Callback callback) { + mContext = context; + mSourceUri = sourceUri; + mCallback = callback; if (destination == null) { - this.destinationFile = getNewFile(context, sourceUri); + mDestinationFile = getNewFile(context, selectedImageUri); } else { - this.destinationFile = destination; + mDestinationFile = destination; } - saveFileName = PREFIX_IMG + new SimpleDateFormat(TIME_STAMP_NAME).format(new Date( - System.currentTimeMillis())); + mSelectedImageUri = selectedImageUri; } public static File getFinalSaveDirectory(Context context, Uri sourceUri) { @@ -114,12 +158,64 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG); } + /** + * Remove the files in the auxiliary directory whose names are the same as + * the source image. + * @param contentResolver The application's contentResolver + * @param srcContentUri The content Uri for the source image. + */ + public static void deleteAuxFiles(ContentResolver contentResolver, + Uri srcContentUri) { + final String[] fullPath = new String[1]; + String[] queryProjection = new String[] { ImageColumns.DATA }; + querySourceFromContentResolver(contentResolver, + srcContentUri, queryProjection, + new ContentResolverQueryCallback() { + @Override + public void onCursorResult(Cursor cursor) { + fullPath[0] = cursor.getString(0); + } + } + ); + if (fullPath[0] != null) { + // Construct the auxiliary directory given the source file's path. + // Then select and delete all the files starting with the same name + // under the auxiliary directory. + File currentFile = new File(fullPath[0]); + + String filename = currentFile.getName(); + int firstDotPos = filename.indexOf("."); + final String filenameNoExt = (firstDotPos == -1) ? filename : + filename.substring(0, firstDotPos); + File auxDir = getLocalAuxDirectory(currentFile); + if (auxDir.exists()) { + FilenameFilter filter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if (name.startsWith(filenameNoExt + ".")) { + return true; + } else { + return false; + } + } + }; + + // Delete all auxiliary files whose name is matching the + // current local image. + File[] auxFiles = auxDir.listFiles(filter); + for (File file : auxFiles) { + file.delete(); + } + } + } + } + public Object getPanoramaXMPData(Uri source, ImagePreset preset) { Object xmp = null; if (preset.isPanoramaSafe()) { InputStream is = null; try { - is = context.getContentResolver().openInputStream(source); + is = mContext.getContentResolver().openInputStream(source); xmp = XmpUtilHelper.extractXMPMeta(is); } catch (FileNotFoundException e) { Log.w(LOGTAG, "Failed to get XMP data from image: ", e); @@ -139,11 +235,11 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { public ExifInterface getExifData(Uri source) { ExifInterface exif = new ExifInterface(); - String mimeType = context.getContentResolver().getType(sourceUri); + String mimeType = mContext.getContentResolver().getType(mSelectedImageUri); if (mimeType.equals(ImageLoader.JPEG_MIME_TYPE)) { InputStream inStream = null; try { - inStream = context.getContentResolver().openInputStream(source); + inStream = mContext.getContentResolver().openInputStream(source); exif.readExif(inStream); } catch (FileNotFoundException e) { Log.w(LOGTAG, "Cannot find file: " + source, e); @@ -175,7 +271,7 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { @Override protected Uri doInBackground(ImagePreset... params) { // TODO: Support larger dimensions for photo saving. - if (params[0] == null || sourceUri == null) { + if (params[0] == null || mSourceUri == null || mSelectedImageUri == null) { return null; } ImagePreset preset = params[0]; @@ -183,19 +279,25 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { Uri uri = null; boolean noBitmap = true; int num_tries = 0; + + // If necessary, move the source file into the auxiliary directory, + // newSourceUri is then pointing to the new location. + // If no file is moved, newSourceUri will be the same as mSourceUri. + Uri newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); + // Stopgap fix for low-memory devices. while (noBitmap) { try { // Try to do bitmap operations, downsample if low-memory - Bitmap bitmap = ImageLoader.loadMutableBitmap(context, sourceUri, options); + Bitmap bitmap = ImageLoader.loadMutableBitmap(mContext, newSourceUri, options); if (bitmap == null) { return null; } CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(), "Saving"); bitmap = pipeline.renderFinalImage(bitmap, preset); - Object xmp = getPanoramaXMPData(sourceUri, preset); - ExifInterface exif = getExifData(sourceUri); + Object xmp = getPanoramaXMPData(mSelectedImageUri, preset); + ExifInterface exif = getExifData(mSelectedImageUri); // Set tags long time = System.currentTimeMillis(); @@ -208,12 +310,23 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { exif.removeCompressedThumbnail(); // If we succeed in writing the bitmap as a jpeg, return a uri. - if (putExifData(this.destinationFile, exif, bitmap)) { - putPanoramaXMPData(this.destinationFile, xmp); - uri = insertContent(context, sourceUri, this.destinationFile, saveFileName, + if (putExifData(mDestinationFile, exif, bitmap)) { + putPanoramaXMPData(mDestinationFile, xmp); + uri = insertContent(mContext, mSelectedImageUri, mDestinationFile, time); } - XmpPresets.writeFilterXMP(context, sourceUri, this.destinationFile, preset); + + // mDestinationFile will save the newSourceUri info in the XMP. + XmpPresets.writeFilterXMP(mContext, newSourceUri, mDestinationFile, preset); + + // Since we have a new image inserted to media store, we can + // safely remove the old one which is selected by the user. + String scheme = mSelectedImageUri.getScheme(); + if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) { + if (mSelectedImageUri.getAuthority().equals(MediaStore.AUTHORITY)) { + mContext.getContentResolver().delete(mSelectedImageUri, null, null); + } + } noBitmap = false; UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, @@ -230,17 +343,73 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { return uri; } + /** + * Move the source file to auxiliary directory if needed and return the Uri + * pointing to this new source file. + * @param srcUri Uri to the source image. + * @param dstFile Providing the destination file info to help to build the + * auxiliary directory and new source file's name. + * @return the newSourceUri pointing to the new source image. + */ + private Uri moveSrcToAuxIfNeeded(Uri srcUri, File dstFile) { + File srcFile = getFileFromUri(mContext, srcUri); + if (srcFile == null) { + Log.d(LOGTAG, "Source file is not a local file, no update."); + return srcUri; + } + + // Get the destination directory and create the auxilliary directory + // if necessary. + File auxDiretory = getLocalAuxDirectory(dstFile); + if (!auxDiretory.exists()) { + auxDiretory.mkdirs(); + } + + // Make sure there is a .nomedia file in the auxiliary directory, such + // that MediaScanner will not report those files under this directory. + File noMedia = new File(auxDiretory, ".nomedia"); + if (!noMedia.exists()) { + try { + noMedia.createNewFile(); + } catch (IOException e) { + Log.e(LOGTAG, "Can't create the nomedia"); + return srcUri; + } + } + // We are using the destination file name such that photos sitting in + // the auxiliary directory are matching the parent directory. + File newSrcFile = new File(auxDiretory, dstFile.getName()); + + if (!newSrcFile.exists()) { + srcFile.renameTo(newSrcFile); + } + + return Uri.fromFile(newSrcFile); + + } + + private static File getLocalAuxDirectory(File dstFile) { + File dstDirectory = dstFile.getParentFile(); + File auxDiretory = new File(dstDirectory + "/" + AUX_DIR_NAME); + return auxDiretory; + } @Override protected void onPostExecute(Uri result) { - if (callback != null) { - callback.onComplete(result); + if (mCallback != null) { + mCallback.onComplete(result); } } private static void querySource(Context context, Uri sourceUri, String[] projection, ContentResolverQueryCallback callback) { ContentResolver contentResolver = context.getContentResolver(); + querySourceFromContentResolver(contentResolver, sourceUri, projection, callback); + } + + private static void querySourceFromContentResolver( + ContentResolver contentResolver, Uri sourceUri, String[] projection, + ContentResolverQueryCallback callback) { Cursor cursor = null; try { cursor = contentResolver.query(sourceUri, projection, null, null, @@ -258,18 +427,51 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { } private static File getSaveDirectory(Context context, Uri sourceUri) { - final File[] dir = new File[1]; - querySource(context, sourceUri, new String[] { - ImageColumns.DATA - }, - new ContentResolverQueryCallback() { + File file = getFileFromUri(context, sourceUri); + if (file != null) { + return file.getParentFile(); + } else { + return null; + } + } - @Override - public void onCursorResult(Cursor cursor) { - dir[0] = new File(cursor.getString(0)).getParentFile(); - } - }); - return dir[0]; + /** + * Construct a File object based on the srcUri. + * @return The file object. Return null if srcUri is invalid or not a local + * file. + */ + private static File getFileFromUri(Context context, Uri srcUri) { + if (srcUri == null) { + Log.e(LOGTAG, "srcUri is null."); + return null; + } + + String scheme = srcUri.getScheme(); + if (scheme == null) { + Log.e(LOGTAG, "scheme is null."); + return null; + } + + final File[] file = new File[1]; + // sourceUri can be a file path or a content Uri, it need to be handled + // differently. + if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { + if (srcUri.getAuthority().equals(MediaStore.AUTHORITY)) { + querySource(context, srcUri, new String[] { + ImageColumns.DATA + }, + new ContentResolverQueryCallback() { + + @Override + public void onCursorResult(Cursor cursor) { + file[0] = new File(cursor.getString(0)); + } + }); + } + } else if (scheme.equals(ContentResolver.SCHEME_FILE)) { + file[0] = new File(srcUri.getPath()); + } + return file[0]; } /** @@ -302,16 +504,16 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { /** * Insert the content (saved file) with proper source photo properties. */ - public static Uri insertContent(Context context, Uri sourceUri, File file, String saveFileName, + private static Uri insertContent(Context context, Uri sourceUri, File file, long time) { time /= 1000; final ContentValues values = new ContentValues(); - values.put(Images.Media.TITLE, saveFileName); + values.put(Images.Media.TITLE, file.getName()); values.put(Images.Media.DISPLAY_NAME, file.getName()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(Images.Media.DATE_TAKEN, time); - values.put(Images.Media.DATE_MODIFIED, time); + values.put(Images.Media.DATE_MODIFIED, System.currentTimeMillis()); values.put(Images.Media.DATE_ADDED, time); values.put(Images.Media.ORIENTATION, 0); values.put(Images.Media.DATA, file.getAbsolutePath()); diff --git a/src/com/android/gallery3d/util/SaveVideoFileUtils.java b/src/com/android/gallery3d/util/SaveVideoFileUtils.java index e2c5f51b9..da0970b1d 100644 --- a/src/com/android/gallery3d/util/SaveVideoFileUtils.java +++ b/src/com/android/gallery3d/util/SaveVideoFileUtils.java @@ -25,17 +25,13 @@ import android.os.Environment; import android.provider.MediaStore.Video; import android.provider.MediaStore.Video.VideoColumns; +import com.android.gallery3d.filtershow.tools.SaveCopyTask.ContentResolverQueryCallback; + import java.io.File; import java.sql.Date; import java.text.SimpleDateFormat; public class SaveVideoFileUtils { - // Copy from SaveCopyTask.java in terms of how to handle the destination - // path and filename : querySource() and getSaveDirectory(). - public interface ContentResolverQueryCallback { - void onCursorResult(Cursor cursor); - } - // This function can decide which folder to save the video file, and generate // the needed information for the video file including filename. public static SaveVideoFileInfo getDstMp4FileInfo(String fileNameFormat, |