diff options
author | Vasu Nori <vnori@google.com> | 2010-11-02 21:55:30 -0700 |
---|---|---|
committer | Vasu Nori <vnori@google.com> | 2010-11-04 17:57:24 -0700 |
commit | 5be894e636522addc40dad3b631f0249e6cc25cf (patch) | |
tree | d5668cf025397ddb4b6951e11012a44cfc466213 | |
parent | e84c00f4a7dec8c670eeef013b3cd6ecc7277de3 (diff) | |
download | frameworks_base-5be894e636522addc40dad3b631f0249e6cc25cf.zip frameworks_base-5be894e636522addc40dad3b631f0249e6cc25cf.tar.gz frameworks_base-5be894e636522addc40dad3b631f0249e6cc25cf.tar.bz2 |
add API to return Uri for the given downloaded file id & get mimetype
Change-Id: I1f5dd734e394db0056579a3a0c26862fee27981e
-rw-r--r-- | api/current.xml | 24 | ||||
-rw-r--r-- | core/java/android/app/DownloadManager.java | 86 | ||||
-rw-r--r-- | core/java/android/provider/Downloads.java | 17 | ||||
-rw-r--r-- | core/jni/android_database_SQLiteDatabase.cpp | 3 |
4 files changed, 125 insertions, 5 deletions
diff --git a/api/current.xml b/api/current.xml index a3428db..263648d 100644 --- a/api/current.xml +++ b/api/current.xml @@ -26295,6 +26295,19 @@ <parameter name="request" type="android.app.DownloadManager.Request"> </parameter> </method> +<method name="getUriForDownloadedFile" + return="android.net.Uri" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="long"> +</parameter> +</method> <method name="openDownloadedFile" return="android.os.ParcelFileDescriptor" abstract="false" @@ -26809,6 +26822,17 @@ <parameter name="value" type="java.lang.String"> </parameter> </method> +<method name="allowScanningByMediaScanner" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="setAllowedNetworkTypes" return="android.app.DownloadManager.Request" abstract="false" diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index 592a63b..08ccab6 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -27,6 +27,7 @@ import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.provider.Downloads; +import android.util.Log; import android.util.Pair; import java.io.File; @@ -284,6 +285,7 @@ public class DownloadManager { private static final String[] COLUMNS = new String[] { COLUMN_ID, COLUMN_MEDIAPROVIDER_URI, + Downloads.Impl.COLUMN_DESTINATION, COLUMN_TITLE, COLUMN_DESCRIPTION, COLUMN_URI, @@ -294,13 +296,14 @@ public class DownloadManager { COLUMN_REASON, COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP, - COLUMN_LOCAL_FILENAME + COLUMN_LOCAL_FILENAME, }; // columns to request from DownloadProvider private static final String[] UNDERLYING_COLUMNS = new String[] { Downloads.Impl._ID, Downloads.Impl.COLUMN_MEDIAPROVIDER_URI, + Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.COLUMN_TITLE, Downloads.Impl.COLUMN_DESCRIPTION, Downloads.Impl.COLUMN_URI, @@ -309,14 +312,14 @@ public class DownloadManager { Downloads.Impl.COLUMN_STATUS, Downloads.Impl.COLUMN_CURRENT_BYTES, Downloads.Impl.COLUMN_LAST_MODIFICATION, - Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.COLUMN_FILE_NAME_HINT, Downloads.Impl._DATA, }; private static final Set<String> LONG_COLUMNS = new HashSet<String>( Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_REASON, - COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP)); + COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP, + Downloads.Impl.COLUMN_DESTINATION)); /** * This class contains all the information necessary to request a new download. The URI is the @@ -348,6 +351,7 @@ public class DownloadManager { private boolean mRoamingAllowed = true; private int mAllowedNetworkTypes = ~0; // default to all network types allowed private boolean mIsVisibleInDownloadsUi = true; + private boolean mScannable = false; /** * This download is visible but only shows in the notifications @@ -389,7 +393,10 @@ public class DownloadManager { * Set the local destination for the downloaded file. Must be a file URI to a path on * external storage, and the calling application must have the WRITE_EXTERNAL_STORAGE * permission. - * + * <p> + * The downloaded file is not scanned by MediaScanner. + * But it can be made scannable by calling {@link #allowScanningByMediaScanner()}. + * <p> * By default, downloads are saved to a generated filename in the shared download cache and * may be deleted by the system at any time to reclaim space. * @@ -403,6 +410,9 @@ public class DownloadManager { /** * Set the local destination for the downloaded file to a path within the application's * external files directory (as returned by {@link Context#getExternalFilesDir(String)}. + * <p> + * The downloaded file is not scanned by MediaScanner. + * But it can be made scannable by calling {@link #allowScanningByMediaScanner()}. * * @param context the {@link Context} to use in determining the external files directory * @param dirType the directory type to pass to {@link Context#getExternalFilesDir(String)} @@ -419,6 +429,9 @@ public class DownloadManager { * Set the local destination for the downloaded file to a path within the public external * storage directory (as returned by * {@link Environment#getExternalStoragePublicDirectory(String)}. + *<p> + * The downloaded file is not scanned by MediaScanner. + * But it can be made scannable by calling {@link #allowScanningByMediaScanner()}. * * @param dirType the directory type to pass to * {@link Environment#getExternalStoragePublicDirectory(String)} @@ -438,6 +451,14 @@ public class DownloadManager { } /** + * If the file to be downloaded is to be scanned by MediaScanner, this method + * should be called before {@link DownloadManager#enqueue(Request)} is called. + */ + public void allowScanningByMediaScanner() { + mScannable = true; + } + + /** * Add an HTTP header to be included with the download request. The header will be added to * the end of the list. * @param header HTTP header name @@ -583,6 +604,8 @@ public class DownloadManager { values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE); } + // is the file supposed to be media-scannable? + values.put(Downloads.Impl.COLUMN_MEDIA_SCANNED, (mScannable) ? 0 : 2); if (!mRequestHeaders.isEmpty()) { encodeHttpHeaders(values); @@ -868,6 +891,58 @@ public class DownloadManager { } /** + * Returns {@link Uri} for the given downloaded file id, if the file is + * downloaded successfully. otherwise, null is returned. + *<p> + * If the specified downloaded file is in external storage (for example, /sdcard dir), + * then it is assumed to be safe for anyone to read and the returned {@link Uri} can be used + * by any app to access the downloaded file. + * + * @param id the id of the downloaded file. + * @return the {@link Uri} for the given downloaded file id, if donload was successful. null + * otherwise. + */ + public Uri getUriForDownloadedFile(long id) { + // to check if the file is in cache, get its destination from the database + Query query = new Query().setFilterById(id); + Cursor cursor = null; + try { + cursor = query(query); + if (cursor == null) { + return null; + } + while (cursor.moveToFirst()) { + int status = cursor.getInt(cursor.getColumnIndexOrThrow( + DownloadManager.COLUMN_STATUS)); + if (DownloadManager.STATUS_SUCCESSFUL == status) { + int indx = cursor.getColumnIndexOrThrow( + Downloads.Impl.COLUMN_DESTINATION); + int destination = cursor.getInt(indx); + // TODO: if we ever add API to DownloadManager to let the caller specify + // non-external storage for a donloaded file, then the following code + // should also check for that destination. + if (destination == Downloads.Impl.DESTINATION_CACHE_PARTITION || + destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING || + destination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE) { + // return private uri + return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id); + } else { + // return public uri + return ContentUris.withAppendedId( + Downloads.Impl.PUBLICLY_ACCESSIBLE_DOWNLOADS_URI, id); + } + } + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + // downloaded file not found or its status is not 'successfully completed' + return null; + } + + /** * Restart the given downloads, which must have already completed (successfully or not). This * method will only work when called from within the download manager's process. * @param ids the IDs of the downloads @@ -1088,6 +1163,9 @@ public class DownloadManager { if (column.equals(COLUMN_BYTES_DOWNLOADED_SO_FAR)) { return getUnderlyingLong(Downloads.Impl.COLUMN_CURRENT_BYTES); } + if (column.equals(Downloads.Impl.COLUMN_DESTINATION)) { + return getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION); + } assert column.equals(COLUMN_LAST_MODIFIED_TIMESTAMP); return getUnderlyingLong(Downloads.Impl.COLUMN_LAST_MODIFICATION); } diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index 7054888..65adef9 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -87,6 +87,16 @@ public final class Downloads { public static final Uri ALL_DOWNLOADS_CONTENT_URI = Uri.parse("content://downloads/all_downloads"); + /** URI segment to access a publicly accessible downloaded file */ + public static final String PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT = "public_downloads"; + + /** + * The content URI for accessing publicly accessible downloads (i.e., it requires no + * permissions to access this downloaded file) + */ + public static final Uri PUBLICLY_ACCESSIBLE_DOWNLOADS_URI = + Uri.parse("content://downloads/" + PUBLICLY_ACCESSIBLE_DOWNLOADS_URI_SEGMENT); + /** * Broadcast Action: this is sent by the download manager to the app * that had initiated a download when that download completes. The @@ -358,6 +368,13 @@ public final class Downloads { */ public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri"; + /** + * The column that is used to remember whether the media scanner was invoked. + * It can take the values: null or 0(not scanned), 1(scanned), 2 (not scannable). + * <P>Type: TEXT</P> + */ + public static final String COLUMN_MEDIA_SCANNED = "scanned"; + /* * Lists the destinations that an application can specify for a download. */ diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp index 1b68ba9..7aeed98 100644 --- a/core/jni/android_database_SQLiteDatabase.cpp +++ b/core/jni/android_database_SQLiteDatabase.cpp @@ -78,7 +78,8 @@ static char *createStr(const char *path, short extra) { static void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) { // skip printing this message if it is due to certain types of errors if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT) return; - LOGI("sqlite returned: error code = %d, msg = %s\n", iErrCode, zMsg); + // print databasename, errorcode and msg + LOGI("sqlite returned: error code = %d, msg = %s, db=%s\n", iErrCode, zMsg, databaseName); } // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. |