summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasu Nori <vnori@google.com>2010-11-02 21:55:30 -0700
committerVasu Nori <vnori@google.com>2010-11-04 17:57:24 -0700
commit5be894e636522addc40dad3b631f0249e6cc25cf (patch)
treed5668cf025397ddb4b6951e11012a44cfc466213
parente84c00f4a7dec8c670eeef013b3cd6ecc7277de3 (diff)
downloadframeworks_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.xml24
-rw-r--r--core/java/android/app/DownloadManager.java86
-rw-r--r--core/java/android/provider/Downloads.java17
-rw-r--r--core/jni/android_database_SQLiteDatabase.cpp3
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.