1 // Copyright 2011 Google Inc. 2 // All Rights Reserved. 3 4 package com.android.mms; 5 6 import java.io.File; 7 import java.io.FileNotFoundException; 8 9 import android.content.ContentProvider; 10 import android.content.ContentValues; 11 import android.content.Context; 12 import android.content.UriMatcher; 13 import android.database.Cursor; 14 import android.net.Uri; 15 import android.os.ParcelFileDescriptor; 16 import android.util.Log; 17 18 /** 19 * The TempFileProvider manages a uri, backed by a file, for passing to the camera app for 20 * capturing pictures and videos and storing the data in a file in the messaging app. 21 */ 22 public class TempFileProvider extends ContentProvider { 23 private static String TAG = "TempFileProvider"; 24 25 /** 26 * The content:// style URL for this table 27 */ 28 public static final Uri SCRAP_CONTENT_URI = Uri.parse("content://mms_temp_file/scrapSpace"); 29 30 private static final int MMS_SCRAP_SPACE = 1; 31 private static final UriMatcher sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH); 32 static { 33 sURLMatcher.addURI("mms_temp_file", "scrapSpace", MMS_SCRAP_SPACE); 34 } 35 36 @Override 37 public boolean onCreate() { 38 return true; 39 } 40 41 @Override 42 public Cursor query(Uri uri, String[] projection, 43 String selection, String[] selectionArgs, String sortOrder) { 44 return null; 45 } 46 47 @Override 48 public Uri insert(Uri uri, ContentValues values) { 49 return null; 50 } 51 52 @Override 53 public int delete(Uri uri, String selection, String[] selectionArgs) { 54 return 0; 55 } 56 57 @Override 58 public int update(Uri uri, ContentValues values, 59 String selection, String[] selectionArgs) { 60 return 0; 61 } 62 63 private ParcelFileDescriptor getTempStoreFd(String mode) { 64 String fileName = getScrapPath(getContext()); 65 ParcelFileDescriptor pfd = null; 66 67 try { 68 File file = new File(fileName); 69 70 // make sure the path is valid and directories created for this file. 71 File parentFile = file.getParentFile(); 72 if (!parentFile.exists() && !parentFile.mkdirs()) { 73 Log.e(TAG, "[TempFileProvider] tempStoreFd: " + parentFile.getPath() + 74 "does not exist!"); 75 return null; 76 } 77 78 int modeFlags; 79 if (mode.equals("r")) { 80 modeFlags = ParcelFileDescriptor.MODE_READ_ONLY; 81 } else { 82 modeFlags = ParcelFileDescriptor.MODE_READ_WRITE 83 | ParcelFileDescriptor.MODE_CREATE 84 | ParcelFileDescriptor.MODE_TRUNCATE; 85 } 86 pfd = ParcelFileDescriptor.open(file, modeFlags); 87 } catch (Exception ex) { 88 Log.e(TAG, "getTempStoreFd: error creating pfd for " + fileName, ex); 89 } 90 91 return pfd; 92 } 93 94 @Override 95 public String getType(Uri uri) { 96 return "*/*"; 97 } 98 99 @Override 100 public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 101 // if the url is "content://mms/takePictureTempStore", then it means the requester 102 // wants a file descriptor to write image data to. 103 104 ParcelFileDescriptor fd = null; 105 int match = sURLMatcher.match(uri); 106 107 if (Log.isLoggable(TAG, Log.VERBOSE)) { 108 Log.d(TAG, "openFile: uri=" + uri + ", mode=" + mode); 109 } 110 111 switch (match) { 112 case MMS_SCRAP_SPACE: 113 fd = getTempStoreFd(mode); 114 break; 115 } 116 117 return fd; 118 } 119 120 121 /** 122 * This is the scrap file we use to store the media attachment when the user 123 * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app, 124 * which streams the captured image to the uri. Internally we write the media content 125 * to this file. It's named '.temp.jpg' so Gallery won't pick it up. 126 */ 127 public static String getScrapPath(Context context, String fileName) { 128 return context.getExternalCacheDir().getAbsolutePath() + "/" + fileName; 129 } 130 131 public static String getScrapPath(Context context) { 132 return getScrapPath(context, ".temp.jpg"); 133 } 134 135 /** 136 * renameScrapFile renames the single scrap file to a new name so newer uses of the scrap 137 * file won't overwrite the previously captured data. 138 * @param fileExtension file extension for the temp file, typically ".jpg" or ".3gp" 139 * @param uniqueIdentifier a separator to add to the file to make it unique, 140 * such as the slide number. This parameter can be empty or null. 141 * @return uri of renamed file. If there's an error renaming, null will be returned 142 */ 143 public static Uri renameScrapFile(String fileExtension, String uniqueIdentifier, 144 Context context) { 145 String filePath = getScrapPath(context); 146 // There's only a single scrap file, but there can be several slides. We rename 147 // the scrap file to a new scrap file with the slide number as part of the filename. 148 149 // Replace the filename ".temp.jpg" with ".temp#.[jpg | 3gp]" where # is the unique 150 // identifier. The content of the file may be a picture or a .3gp video. 151 if (uniqueIdentifier == null) { 152 uniqueIdentifier = ""; 153 } 154 File newTempFile = new File(getScrapPath(context, ".temp" + uniqueIdentifier + 155 fileExtension)); 156 File oldTempFile = new File(filePath); 157 // remove any existing file before rename 158 boolean deleted = newTempFile.delete(); 159 if (!oldTempFile.renameTo(newTempFile)) { 160 return null; 161 } 162 return Uri.fromFile(newTempFile); 163 } 164 165 /** 166 * Pass in a path to a file and this function will return true if it thinks the path 167 * points to one of its scrap files. 168 * @param path full path of a file 169 * @return true if path is a scrap file path 170 */ 171 public static boolean isTempFile(String path) { 172 // An admittedly weak determination of a temp file, but sufficient for current needs. 173 // For now, the penalty of returning true for a file that isn't a temp file is simply 174 // not storing the file's thumbnail in an on-disk thumbnail cache. 175 return path.contains(".temp"); 176 } 177 } 178