SaveCopyTask.java revision ae70ae473dcd674d61c9e6a79afcf57f825f7302
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.photoeditor; 18 19import android.content.ContentResolver; 20import android.content.ContentValues; 21import android.content.Context; 22import android.database.Cursor; 23import android.graphics.Bitmap; 24import android.net.Uri; 25import android.os.AsyncTask; 26import android.os.Environment; 27import android.provider.MediaStore.Images; 28import android.provider.MediaStore.Images.ImageColumns; 29import android.view.Gravity; 30import android.widget.Toast; 31 32import com.android.gallery3d.R; 33 34import java.io.File; 35import java.sql.Date; 36import java.text.SimpleDateFormat; 37 38/** 39 * Asynchronous task for saving edited photo as a new copy. 40 */ 41public class SaveCopyTask extends AsyncTask<Bitmap, Void, Uri> { 42 43 /** 44 * Callback for the completed asynchronous task. 45 */ 46 public interface Callback { 47 48 void onComplete(Uri result); 49 } 50 51 private static final String TIME_STAMP_NAME = "'IMG'_yyyyMMdd_HHmmss"; 52 private static final int INDEX_DATE_TAKEN = 0; 53 private static final int INDEX_LATITUDE = 1; 54 private static final int INDEX_LONGITUDE = 2; 55 56 private static final String[] IMAGE_PROJECTION = new String[] { 57 ImageColumns.DATE_TAKEN, 58 ImageColumns.LATITUDE, 59 ImageColumns.LONGITUDE, 60 }; 61 62 private final Context context; 63 private final Uri sourceUri; 64 private final Callback callback; 65 private final String albumName; 66 private final String saveFileName; 67 68 public SaveCopyTask(Context context, Uri sourceUri, Callback callback) { 69 this.context = context; 70 this.sourceUri = sourceUri; 71 this.callback = callback; 72 73 albumName = context.getString(R.string.edited_photo_bucket_name); 74 saveFileName = new SimpleDateFormat(TIME_STAMP_NAME).format( 75 new Date(System.currentTimeMillis())); 76 } 77 78 /** 79 * The task should be executed with one given bitmap to be saved. 80 */ 81 @Override 82 protected Uri doInBackground(Bitmap... params) { 83 // TODO: Support larger dimensions for photo saving. 84 if (params[0] == null) { 85 return null; 86 } 87 Bitmap bitmap = params[0]; 88 File file = save(bitmap); 89 Uri uri = (file != null) ? insertContent(file) : null; 90 bitmap.recycle(); 91 return uri; 92 } 93 94 @Override 95 protected void onPostExecute(Uri result) { 96 String message = (result == null) ? context.getString(R.string.saving_failure) 97 : context.getString(R.string.photo_saved, albumName); 98 Toast toast = Toast.makeText(context, message, Toast.LENGTH_SHORT); 99 toast.setGravity(Gravity.CENTER, 0, 0); 100 toast.show(); 101 102 callback.onComplete(result); 103 } 104 105 private File save(Bitmap bitmap) { 106 String directory = Environment.getExternalStorageDirectory().toString() + "/" + albumName; 107 return new BitmapUtils(context).saveBitmap( 108 bitmap, directory, saveFileName, Bitmap.CompressFormat.JPEG); 109 } 110 111 /** 112 * Insert the content (saved file) with proper source photo properties. 113 */ 114 private Uri insertContent(File file) { 115 long now = System.currentTimeMillis() / 1000; 116 long dateTaken = now; 117 double latitude = 0f; 118 double longitude = 0f; 119 120 ContentResolver contentResolver = context.getContentResolver(); 121 Cursor cursor = null; 122 try { 123 cursor = contentResolver.query(sourceUri, IMAGE_PROJECTION, null, null, null); 124 if ((cursor != null) && cursor.moveToNext()) { 125 dateTaken = cursor.getLong(INDEX_DATE_TAKEN); 126 latitude = cursor.getDouble(INDEX_LATITUDE); 127 longitude = cursor.getDouble(INDEX_LONGITUDE); 128 } 129 } catch (Exception e) { 130 // Ignore error for lacking property columns from the source. 131 } finally { 132 if (cursor != null) { 133 cursor.close(); 134 } 135 } 136 137 ContentValues values = new ContentValues(); 138 values.put(Images.Media.TITLE, saveFileName); 139 values.put(Images.Media.DISPLAY_NAME, saveFileName); 140 values.put(Images.Media.MIME_TYPE, "image/jpeg"); 141 values.put(Images.Media.DATE_TAKEN, dateTaken); 142 values.put(Images.Media.DATE_MODIFIED, now); 143 values.put(Images.Media.DATE_ADDED, now); 144 values.put(Images.Media.ORIENTATION, 0); 145 values.put(Images.Media.DATA, file.getAbsolutePath()); 146 values.put(Images.Media.SIZE, file.length()); 147 148 // TODO: Change || to && after the default location issue is fixed. 149 if ((latitude != 0f) || (longitude != 0f)) { 150 values.put(Images.Media.LATITUDE, latitude); 151 values.put(Images.Media.LONGITUDE, longitude); 152 } 153 return contentResolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values); 154 } 155} 156