import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.provider.Downloads;
-import android.provider.Settings;
import android.provider.MediaStore.Images;
+import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Pair;
* request that a URI be downloaded to a particular destination file. The download manager will
* conduct the download in the background, taking care of HTTP interactions and retrying downloads
* after failures or across connectivity changes and system reboots.
- *
- * Instances of this class should be obtained through
- * {@link android.content.Context#getSystemService(String)} by passing
- * {@link android.content.Context#DOWNLOAD_SERVICE}.
- *
+ * <p>
* Apps that request downloads through this API should register a broadcast receiver for
* {@link #ACTION_NOTIFICATION_CLICKED} to appropriately handle when the user clicks on a running
* download in a notification or from the downloads UI.
- *
+ * <p>
* Note that the application must have the {@link android.Manifest.permission#INTERNET}
* permission to use this class.
*/
+@SystemService(Context.DOWNLOAD_SERVICE)
public class DownloadManager {
/**
*/
public final static String COLUMN_STATUS = Downloads.Impl.COLUMN_STATUS;
+ /** {@hide} */
+ public static final String COLUMN_FILE_NAME_HINT = Downloads.Impl.COLUMN_FILE_NAME_HINT;
+
/**
* Provides more detail on the status of the download. Its meaning depends on the value of
* {@link #COLUMN_STATUS}.
*/
public static final String COLUMN_MEDIAPROVIDER_URI = Downloads.Impl.COLUMN_MEDIAPROVIDER_URI;
+ /** {@hide} */
+ public static final String COLUMN_DESTINATION = Downloads.Impl.COLUMN_DESTINATION;
+
/**
* @hide
*/
*/
public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
+ /** {@hide} */
+ @SystemApi
+ public static final String ACTION_DOWNLOAD_COMPLETED =
+ "android.intent.action.DOWNLOAD_COMPLETED";
+
/**
* columns to request from DownloadProvider.
* @hide
*/
public static final String[] UNDERLYING_COLUMNS = new String[] {
- Downloads.Impl._ID,
- Downloads.Impl._DATA + " AS " + COLUMN_LOCAL_FILENAME,
- Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
- Downloads.Impl.COLUMN_DESTINATION,
- Downloads.Impl.COLUMN_TITLE,
- Downloads.Impl.COLUMN_DESCRIPTION,
- Downloads.Impl.COLUMN_URI,
- Downloads.Impl.COLUMN_STATUS,
- Downloads.Impl.COLUMN_FILE_NAME_HINT,
- Downloads.Impl.COLUMN_MIME_TYPE + " AS " + COLUMN_MEDIA_TYPE,
- Downloads.Impl.COLUMN_TOTAL_BYTES + " AS " + COLUMN_TOTAL_SIZE_BYTES,
- Downloads.Impl.COLUMN_LAST_MODIFICATION + " AS " + COLUMN_LAST_MODIFIED_TIMESTAMP,
- Downloads.Impl.COLUMN_CURRENT_BYTES + " AS " + COLUMN_BYTES_DOWNLOADED_SO_FAR,
- Downloads.Impl.COLUMN_ALLOW_WRITE,
- /* add the following 'computed' columns to the cursor.
- * they are not 'returned' by the database, but their inclusion
- * eliminates need to have lot of methods in CursorTranslator
- */
- "'placeholder' AS " + COLUMN_LOCAL_URI,
- "'placeholder' AS " + COLUMN_REASON
+ DownloadManager.COLUMN_ID,
+ DownloadManager.COLUMN_LOCAL_FILENAME,
+ DownloadManager.COLUMN_MEDIAPROVIDER_URI,
+ DownloadManager.COLUMN_DESTINATION,
+ DownloadManager.COLUMN_TITLE,
+ DownloadManager.COLUMN_DESCRIPTION,
+ DownloadManager.COLUMN_URI,
+ DownloadManager.COLUMN_STATUS,
+ DownloadManager.COLUMN_FILE_NAME_HINT,
+ DownloadManager.COLUMN_MEDIA_TYPE,
+ DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
+ DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP,
+ DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR,
+ DownloadManager.COLUMN_ALLOW_WRITE,
+ DownloadManager.COLUMN_LOCAL_URI,
+ DownloadManager.COLUMN_REASON
};
/**
private int mFlags = 0;
private boolean mIsVisibleInDownloadsUi = true;
private boolean mScannable = false;
- private boolean mUseSystemCache = false;
/** if a file is designated as a MediaScanner scannable file, the following value is
* stored in the database column {@link Downloads.Impl#COLUMN_MEDIA_SCANNED}.
*/
}
/**
- * Set the local destination for the downloaded file to the system cache dir (/cache).
- * This is only available to System apps with the permission
- * {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM}.
- * <p>
- * The downloaded file is not scanned by MediaScanner.
- * But it can be made scannable by calling {@link #allowScanningByMediaScanner()}.
- * <p>
- * Files downloaded to /cache may be deleted by the system at any time to reclaim space.
- *
- * @return this object
- * @hide
- */
- public Request setDestinationToSystemCache() {
- mUseSystemCache = true;
- return this;
- }
-
- /**
* 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)}.
values.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, packageName);
if (mDestinationUri != null) {
- values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_FILE_URI);
- values.put(Downloads.Impl.COLUMN_FILE_NAME_HINT, mDestinationUri.toString());
+ values.put(Downloads.Impl.COLUMN_DESTINATION,
+ Downloads.Impl.DESTINATION_FILE_URI);
+ values.put(Downloads.Impl.COLUMN_FILE_NAME_HINT,
+ mDestinationUri.toString());
} else {
values.put(Downloads.Impl.COLUMN_DESTINATION,
- (this.mUseSystemCache) ?
- Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION :
- Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE);
+ Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE);
}
// is the file supposed to be media-scannable?
values.put(Downloads.Impl.COLUMN_MEDIA_SCANNED, (mScannable) ? SCANNABLE_VALUE_YES :
private long[] mIds = null;
private Integer mStatusFlags = null;
+ private String mFilterString = null;
private String mOrderByColumn = Downloads.Impl.COLUMN_LAST_MODIFICATION;
private int mOrderDirection = ORDER_DESCENDING;
private boolean mOnlyIncludeVisibleInDownloadsUi = false;
}
/**
+ *
+ * Include only the downloads that contains the given string in its name.
+ * @return this object
+ * @hide
+ */
+ public Query setFilterByString(@Nullable String filter) {
+ mFilterString = filter;
+ return this;
+ }
+
+ /**
* Include only downloads with status matching any the given status flags.
* @param flags any combination of the STATUS_* bit flags
* @return this object
List<String> selectionParts = new ArrayList<String>();
String[] selectionArgs = null;
- if (mIds != null) {
- selectionParts.add(getWhereClauseForIds(mIds));
- selectionArgs = getWhereArgsForIds(mIds);
+ int whereArgsCount = (mIds == null) ? 0 : mIds.length;
+ whereArgsCount = (mFilterString == null) ? whereArgsCount : whereArgsCount + 1;
+ selectionArgs = new String[whereArgsCount];
+
+ if (whereArgsCount > 0) {
+ if (mIds != null) {
+ selectionParts.add(getWhereClauseForIds(mIds));
+ getWhereArgsForIds(mIds, selectionArgs);
+ }
+
+ if (mFilterString != null) {
+ selectionParts.add(Downloads.Impl.COLUMN_TITLE + " LIKE ?");
+ selectionArgs[selectionArgs.length - 1] = "%" + mFilterString + "%";
+ }
}
if (mStatusFlags != null) {
*/
static String[] getWhereArgsForIds(long[] ids) {
String[] whereArgs = new String[ids.length];
+ return getWhereArgsForIds(ids, whereArgs);
+ }
+
+ /**
+ * Get selection args for a clause returned by {@link #getWhereClauseForIds(long[])}
+ * and write it to the supplied args array.
+ */
+ static String[] getWhereArgsForIds(long[] ids, String[] args) {
+ assert(args.length >= ids.length);
for (int i = 0; i < ids.length; i++) {
- whereArgs[i] = Long.toString(ids[i]);
+ args[i] = Long.toString(ids[i]);
}
- return whereArgs;
+ return args;
}
+
/**
* This class wraps a cursor returned by DownloadProvider -- the "underlying cursor" -- and
* presents a different set of columns, those defined in the DownloadManager.COLUMN_* constants.