AttachmentProvider.java revision 301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10
196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License. 696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at 796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and 1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License. 1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email.provider; 1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 19c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport com.android.email.mail.internet.MimeUtility; 2096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 2196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.content.ContentProvider; 227436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Predaimport android.content.ContentResolver; 2396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.content.ContentValues; 2496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.database.Cursor; 2596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.database.MatrixCursor; 2696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 2796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.graphics.Bitmap; 2896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.graphics.BitmapFactory; 2996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.net.Uri; 3096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.os.ParcelFileDescriptor; 3196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 32c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.io.File; 33c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.io.FileNotFoundException; 34c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.io.FileOutputStream; 35c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.io.IOException; 36c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.io.InputStream; 37c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadlerimport java.util.List; 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * A simple ContentProvider that allows file access to Email's attachments. 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class AttachmentProvider extends ContentProvider { 43301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler 44301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler public static final String AUTHORITY = "com.android.email.attachmentprovider"; 45301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler public static final Uri CONTENT_URI = Uri.parse( "content://" + AUTHORITY); 4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 4796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private static final String FORMAT_RAW = "RAW"; 4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private static final String FORMAT_THUMBNAIL = "THUMBNAIL"; 4996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static class AttachmentProviderColumns { 5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static final String _ID = "_id"; 5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static final String DATA = "_data"; 5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static final String DISPLAY_NAME = "_display_name"; 5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static final String SIZE = "_size"; 5596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 5696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 57a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public static Uri getAttachmentUri(EmailContent.Account account, long id) { 5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return CONTENT_URI.buildUpon() 5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(account.getUuid() + ".db") 6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(Long.toString(id)) 6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(FORMAT_RAW) 6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .build(); 6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 65a290f503f14432163f74548a5e5d1dc5003ad049Marc Blank public static Uri getAttachmentThumbnailUri(EmailContent.Account account, long id, 66c0033f24a26a08c47aa38d957f42cf63cfa3c345Andrew Stadler int width, int height) { 6796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return CONTENT_URI.buildUpon() 6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(account.getUuid() + ".db") 6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(Long.toString(id)) 7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(FORMAT_THUMBNAIL) 7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(Integer.toString(width)) 7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(Integer.toString(height)) 7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .build(); 7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public static Uri getAttachmentUri(String db, long id) { 7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return CONTENT_URI.buildUpon() 7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(db) 7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(Long.toString(id)) 8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .appendPath(FORMAT_RAW) 8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project .build(); 8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public boolean onCreate() { 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /* 8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * We use the cache dir as a temporary directory (since Android doesn't give us one) so 8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * on startup we'll clean up any .tmp files from the last run. 8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 9096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project File[] files = getContext().getCacheDir().listFiles(); 9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project for (File file : files) { 92aeeefedb43c40e887850654ac88270755f5631c1Mihai Preda String filename = file.getName(); 93aeeefedb43c40e887850654ac88270755f5631c1Mihai Preda if (filename.endsWith(".tmp") || filename.startsWith("thmb_")) { 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project file.delete(); 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return true; 9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 100301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler /** 101301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Returns the mime type for a given attachment. There are three possible results: 102301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * - If thumbnail Uri, always returns "image/png" (even if there's no attachment) 103301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * - If the attachment does not exist, returns null 104301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * - Returns the mime type of the attachment 105301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler */ 10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getType(Uri uri) { 10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project List<String> segments = uri.getPathSegments(); 10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String dbName = segments.get(0); 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String id = segments.get(1); 11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String format = segments.get(2); 11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (FORMAT_THUMBNAIL.equals(format)) { 11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return "image/png"; 11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else { 11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String path = getContext().getDatabasePath(dbName).getAbsolutePath(); 11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SQLiteDatabase db = null; 11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Cursor cursor = null; 11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project db = SQLiteDatabase.openDatabase(path, null, 0); 12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor = db.query( 12296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "attachments", 12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new String[] { "mime_type" }, 12496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "id = ?", 12596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new String[] { id }, 12696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null, 12796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null, 12896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null); 12996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor.moveToFirst(); 13096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String type = cursor.getString(0); 13196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor.close(); 13296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project db.close(); 13396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return type; 13496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project finally { 13796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (cursor != null) { 13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor.close(); 13996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 14096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (db != null) { 14196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project db.close(); 14296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 14396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 14496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 14596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 14696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 14796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 148301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler /** 149301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Open an attachment file. There are two "modes" - "raw", which returns an actual file, 150301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * and "thumbnail", which attempts to generate a thumbnail image. 151301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 152301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Thumbnails are cached for easy space recovery and cleanup. 153301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 154301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * TODO: The thumbnail mode returns null for its failure cases, instead of throwing 155301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * FileNotFoundException, and should be fixed for consistency. 156301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 157301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * @throws FileNotFoundException 158301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler */ 15996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project List<String> segments = uri.getPathSegments(); 16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String dbName = segments.get(0); 16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String id = segments.get(1); 16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String format = segments.get(2); 16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (FORMAT_THUMBNAIL.equals(format)) { 16696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int width = Integer.parseInt(segments.get(3)); 16796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int height = Integer.parseInt(segments.get(4)); 16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String filename = "thmb_" + dbName + "_" + id; 16996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project File dir = getContext().getCacheDir(); 17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project File file = new File(dir, filename); 17196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (!file.exists()) { 17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Uri attachmentUri = getAttachmentUri(dbName, Long.parseLong(id)); 1735182d80674a1ef90586f52355a21a82e8265c10aMihai Preda Cursor c = query(attachmentUri, 1745182d80674a1ef90586f52355a21a82e8265c10aMihai Preda new String[] { AttachmentProviderColumns.DATA }, null, null, null); 1755182d80674a1ef90586f52355a21a82e8265c10aMihai Preda if (c != null) { 1765182d80674a1ef90586f52355a21a82e8265c10aMihai Preda try { 1775182d80674a1ef90586f52355a21a82e8265c10aMihai Preda if (c.moveToFirst()) { 1785182d80674a1ef90586f52355a21a82e8265c10aMihai Preda attachmentUri = Uri.parse(c.getString(0)); 1795182d80674a1ef90586f52355a21a82e8265c10aMihai Preda } 1805182d80674a1ef90586f52355a21a82e8265c10aMihai Preda } finally { 1815182d80674a1ef90586f52355a21a82e8265c10aMihai Preda c.close(); 1825182d80674a1ef90586f52355a21a82e8265c10aMihai Preda } 1835182d80674a1ef90586f52355a21a82e8265c10aMihai Preda } 1845182d80674a1ef90586f52355a21a82e8265c10aMihai Preda String type = getContext().getContentResolver().getType(attachmentUri); 18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 1865182d80674a1ef90586f52355a21a82e8265c10aMihai Preda InputStream in = 1875182d80674a1ef90586f52355a21a82e8265c10aMihai Preda getContext().getContentResolver().openInputStream(attachmentUri); 18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Bitmap thumbnail = createThumbnail(type, in); 1895182d80674a1ef90586f52355a21a82e8265c10aMihai Preda thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); 19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project FileOutputStream out = new FileOutputStream(file); 19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); 19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project out.close(); 19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project in.close(); 19496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project catch (IOException ioe) { 19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); 20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else { 20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return ParcelFileDescriptor.open( 20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new File(getContext().getDatabasePath(dbName + "_att"), id), 20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ParcelFileDescriptor.MODE_READ_ONLY); 20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int delete(Uri uri, String arg1, String[] arg2) { 21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return 0; 21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 21296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Uri insert(Uri uri, ContentValues values) { 21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 21696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 218301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler /** 219301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Returns a cursor based on the data in the attachments table, or null if the attachment 220301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * is not recorded in the table. 221301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 222301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Supports REST Uri only, for a single row - selection, selection args, and sortOrder are 223301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * ignored (non-null values should probably throw an exception....) 224301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 225301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * TODO: Throws an SQLite exception on a missing DB file (e.g. unknown URI) instead of just 226301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * returning null, as it should. 227301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler */ 22896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 22996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 23096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String sortOrder) { 23196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (projection == null) { 23296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project projection = 23396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new String[] { 23496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project AttachmentProviderColumns._ID, 23596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project AttachmentProviderColumns.DATA, 23696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project }; 23796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 23896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 23996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project List<String> segments = uri.getPathSegments(); 24096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String dbName = segments.get(0); 24196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String id = segments.get(1); 24296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String format = segments.get(2); 24396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String path = getContext().getDatabasePath(dbName).getAbsolutePath(); 24496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String name = null; 24596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int size = -1; 2465182d80674a1ef90586f52355a21a82e8265c10aMihai Preda String contentUri = null; 24796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SQLiteDatabase db = null; 24896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Cursor cursor = null; 24996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 25096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project db = SQLiteDatabase.openDatabase(path, null, 0); 25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor = db.query( 25296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "attachments", 2535182d80674a1ef90586f52355a21a82e8265c10aMihai Preda new String[] { "name", "size", "content_uri" }, 25496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "id = ?", 25596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new String[] { id }, 25696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null, 25796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null, 25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project null); 25996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (!cursor.moveToFirst()) { 26096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 26296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project name = cursor.getString(0); 26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project size = cursor.getInt(1); 2645182d80674a1ef90586f52355a21a82e8265c10aMihai Preda contentUri = cursor.getString(2); 26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project finally { 26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (cursor != null) { 26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project cursor.close(); 26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (db != null) { 27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project db.close(); 27296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 27596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MatrixCursor ret = new MatrixCursor(projection); 27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Object[] values = new Object[projection.length]; 27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project for (int i = 0, count = projection.length; i < count; i++) { 27896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String column = projection[i]; 27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (AttachmentProviderColumns._ID.equals(column)) { 28096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project values[i] = id; 28196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else if (AttachmentProviderColumns.DATA.equals(column)) { 2835182d80674a1ef90586f52355a21a82e8265c10aMihai Preda values[i] = contentUri; 28496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else if (AttachmentProviderColumns.DISPLAY_NAME.equals(column)) { 28696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project values[i] = name; 28796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else if (AttachmentProviderColumns.SIZE.equals(column)) { 28996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project values[i] = size; 29096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ret.addRow(values); 29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return ret; 29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 29796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 29896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return 0; 29996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 30196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private Bitmap createThumbnail(String type, InputStream data) { 30296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if(MimeUtility.mimeTypeMatches(type, "image/*")) { 30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return createImageThumbnail(data); 30496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 30696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 30896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private Bitmap createImageThumbnail(InputStream data) { 30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 31096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Bitmap bitmap = BitmapFactory.decodeStream(data); 31196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return bitmap; 31296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 31396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project catch (OutOfMemoryError oome) { 31496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /* 31596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Improperly downloaded images, corrupt bitmaps and the like can commonly 31696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * cause OOME due to invalid allocation sizes. We're happy with a null bitmap in 31796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * that case. If the system is really out of memory we'll know about it soon 31896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * enough. 31996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 32096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 32196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 32296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project catch (Exception e) { 32396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 32496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 32596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 3267436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda /** 327301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * Resolve attachment id to content URI. Returns the resolved content URI (from the attachment 328301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * DB) or, if not found, simply returns the incoming value. 3297436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda * 3307436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda * @param attachmentUri 3317436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda * @return resolved content URI 332301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * 333301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * TODO: Throws an SQLite exception on a missing DB file (e.g. unknown URI) instead of just 334301ac18bb7f211b473c4f6fa6ec9bb276bbc6c10Andrew Stadler * returning the incoming uri, as it should. 3357436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda */ 3367436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda public static Uri resolveAttachmentIdToContentUri(ContentResolver resolver, Uri attachmentUri) { 3377436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda Cursor c = resolver.query(attachmentUri, 3387436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda new String[] { AttachmentProvider.AttachmentProviderColumns.DATA }, 3397436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda null, null, null); 3407436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda if (c != null) { 3417436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda try { 3427436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda if (c.moveToFirst()) { 3437436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda return Uri.parse(c.getString(0)); 3447436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda } 3457436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda } finally { 3467436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda c.close(); 3477436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda } 3487436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda } 3497436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda return attachmentUri; 3507436601fae756e8bc1f916560a1c2d1f8ce576fcMihai Preda } 35196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 352