Created
March 21, 2012 07:30
-
-
Save wangpeng1/2145469 to your computer and use it in GitHub Desktop.
Downloads.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2010 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.test.DownloadManager; | |
import android.content.ContentResolver; | |
import android.content.ContentUris; | |
import android.content.ContentValues; | |
import android.content.Context; | |
import android.database.Cursor; | |
import android.database.CursorWrapper; | |
import android.net.ConnectivityManager; | |
import android.net.Uri; | |
import android.os.Environment; | |
import android.os.ParcelFileDescriptor; | |
import android.provider.Settings; | |
import android.provider.Settings.SettingNotFoundException; | |
import android.text.TextUtils; | |
import android.util.Pair; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* The download manager is a system service that handles long-running HTTP downloads. Clients may | |
* 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}. | |
* | |
* 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. | |
*/ | |
public class DownloadManager { | |
/** | |
* An identifier for a particular download, unique across the system. Clients use this ID to | |
* make subsequent calls related to the download. | |
*/ | |
public final static String COLUMN_ID = Downloads.Impl._ID; | |
/** | |
* The client-supplied title for this download. This will be displayed in system notifications. | |
* Defaults to the empty string. | |
*/ | |
public final static String COLUMN_TITLE = Downloads.Impl.COLUMN_TITLE; | |
/** | |
* The client-supplied description of this download. This will be displayed in system | |
* notifications. Defaults to the empty string. | |
*/ | |
public final static String COLUMN_DESCRIPTION = Downloads.Impl.COLUMN_DESCRIPTION; | |
/** | |
* URI to be downloaded. | |
*/ | |
public final static String COLUMN_URI = Downloads.Impl.COLUMN_URI; | |
/** | |
* Internet Media Type of the downloaded file. If no value is provided upon creation, this will | |
* initially be null and will be filled in based on the server's response once the download has | |
* started. | |
* | |
* @see <a href="http://www.ietf.org/rfc/rfc1590.txt">RFC 1590, defining Media Types</a> | |
*/ | |
public final static String COLUMN_MEDIA_TYPE = "media_type"; | |
/** | |
* Total size of the download in bytes. This will initially be -1 and will be filled in once | |
* the download starts. | |
*/ | |
public final static String COLUMN_TOTAL_SIZE_BYTES = "total_size"; | |
/** | |
* Uri where downloaded file will be stored. If a destination is supplied by client, that URI | |
* will be used here. Otherwise, the value will initially be null and will be filled in with a | |
* generated URI once the download has started. | |
*/ | |
public final static String COLUMN_LOCAL_URI = "local_uri"; | |
/** | |
* The pathname of the file where the download is stored. | |
*/ | |
public final static String COLUMN_LOCAL_FILENAME = "local_filename"; | |
/** | |
* Current status of the download, as one of the STATUS_* constants. | |
*/ | |
public final static String COLUMN_STATUS = Downloads.Impl.COLUMN_STATUS; | |
/** | |
* Provides more detail on the status of the download. Its meaning depends on the value of | |
* {@link #COLUMN_STATUS}. | |
* | |
* When {@link #COLUMN_STATUS} is {@link #STATUS_FAILED}, this indicates the type of error that | |
* occurred. If an HTTP error occurred, this will hold the HTTP status code as defined in RFC | |
* 2616. Otherwise, it will hold one of the ERROR_* constants. | |
* | |
* When {@link #COLUMN_STATUS} is {@link #STATUS_PAUSED}, this indicates why the download is | |
* paused. It will hold one of the PAUSED_* constants. | |
* | |
* If {@link #COLUMN_STATUS} is neither {@link #STATUS_FAILED} nor {@link #STATUS_PAUSED}, this | |
* column's value is undefined. | |
* | |
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1">RFC 2616 | |
* status codes</a> | |
*/ | |
public final static String COLUMN_REASON = "reason"; | |
/** | |
* Number of bytes download so far. | |
*/ | |
public final static String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far"; | |
/** | |
* Timestamp when the download was last modified, in {@link System#currentTimeMillis | |
* System.currentTimeMillis()} (wall clock time in UTC). | |
*/ | |
public final static String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp"; | |
/** | |
* The URI to the corresponding entry in MediaProvider for this downloaded entry. It is | |
* used to delete the entries from MediaProvider database when it is deleted from the | |
* downloaded list. | |
*/ | |
public static final String COLUMN_MEDIAPROVIDER_URI = Downloads.Impl.COLUMN_MEDIAPROVIDER_URI; | |
/** | |
* Value of {@link #COLUMN_STATUS} when the download is waiting to start. | |
*/ | |
public final static int STATUS_PENDING = 1 << 0; | |
/** | |
* Value of {@link #COLUMN_STATUS} when the download is currently running. | |
*/ | |
public final static int STATUS_RUNNING = 1 << 1; | |
/** | |
* Value of {@link #COLUMN_STATUS} when the download is waiting to retry or resume. | |
*/ | |
public final static int STATUS_PAUSED = 1 << 2; | |
/** | |
* Value of {@link #COLUMN_STATUS} when the download has successfully completed. | |
*/ | |
public final static int STATUS_SUCCESSFUL = 1 << 3; | |
/** | |
* Value of {@link #COLUMN_STATUS} when the download has failed (and will not be retried). | |
*/ | |
public final static int STATUS_FAILED = 1 << 4; | |
/** | |
* Value of COLUMN_ERROR_CODE when the download has completed with an error that doesn't fit | |
* under any other error code. | |
*/ | |
public final static int ERROR_UNKNOWN = 1000; | |
/** | |
* Value of {@link #COLUMN_REASON} when a storage issue arises which doesn't fit under any | |
* other error code. Use the more specific {@link #ERROR_INSUFFICIENT_SPACE} and | |
* {@link #ERROR_DEVICE_NOT_FOUND} when appropriate. | |
*/ | |
public final static int ERROR_FILE_ERROR = 1001; | |
/** | |
* Value of {@link #COLUMN_REASON} when an HTTP code was received that download manager | |
* can't handle. | |
*/ | |
public final static int ERROR_UNHANDLED_HTTP_CODE = 1002; | |
/** | |
* Value of {@link #COLUMN_REASON} when an error receiving or processing data occurred at | |
* the HTTP level. | |
*/ | |
public final static int ERROR_HTTP_DATA_ERROR = 1004; | |
/** | |
* Value of {@link #COLUMN_REASON} when there were too many redirects. | |
*/ | |
public final static int ERROR_TOO_MANY_REDIRECTS = 1005; | |
/** | |
* Value of {@link #COLUMN_REASON} when there was insufficient storage space. Typically, | |
* this is because the SD card is full. | |
*/ | |
public final static int ERROR_INSUFFICIENT_SPACE = 1006; | |
/** | |
* Value of {@link #COLUMN_REASON} when no external storage device was found. Typically, | |
* this is because the SD card is not mounted. | |
*/ | |
public final static int ERROR_DEVICE_NOT_FOUND = 1007; | |
/** | |
* Value of {@link #COLUMN_REASON} when some possibly transient error occurred but we can't | |
* resume the download. | |
*/ | |
public final static int ERROR_CANNOT_RESUME = 1008; | |
/** | |
* Value of {@link #COLUMN_REASON} when the requested destination file already exists (the | |
* download manager will not overwrite an existing file). | |
*/ | |
public final static int ERROR_FILE_ALREADY_EXISTS = 1009; | |
/** | |
* Value of {@link #COLUMN_REASON} when the download has failed because of | |
* {@link NetworkPolicyManager} controls on the requesting application. | |
* | |
* @hide | |
*/ | |
public final static int ERROR_BLOCKED = 1010; | |
/** | |
* Value of {@link #COLUMN_REASON} when the download is paused because some network error | |
* occurred and the download manager is waiting before retrying the request. | |
*/ | |
public final static int PAUSED_WAITING_TO_RETRY = 1; | |
/** | |
* Value of {@link #COLUMN_REASON} when the download is waiting for network connectivity to | |
* proceed. | |
*/ | |
public final static int PAUSED_WAITING_FOR_NETWORK = 2; | |
/** | |
* Value of {@link #COLUMN_REASON} when the download exceeds a size limit for downloads over | |
* the mobile network and the download manager is waiting for a Wi-Fi connection to proceed. | |
*/ | |
public final static int PAUSED_QUEUED_FOR_WIFI = 3; | |
/** | |
* Value of {@link #COLUMN_REASON} when the download is paused for some other reason. | |
*/ | |
public final static int PAUSED_UNKNOWN = 4; | |
/** | |
* Broadcast intent action sent by the download manager when a download completes. | |
*/ | |
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"; | |
/** | |
* Broadcast intent action sent by the download manager when the user clicks on a running | |
* download, either from a system notification or from the downloads UI. | |
*/ | |
public final static String ACTION_NOTIFICATION_CLICKED = | |
"android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"; | |
/** | |
* Intent action to launch an activity to display all downloads. | |
*/ | |
public final static String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS"; | |
/** | |
* Intent extra included with {@link #ACTION_VIEW_DOWNLOADS} to start DownloadApp in | |
* sort-by-size mode. | |
*/ | |
public final static String INTENT_EXTRAS_SORT_BY_SIZE = | |
"android.app.DownloadManager.extra_sortBySize"; | |
/** | |
* Intent extra included with {@link #ACTION_DOWNLOAD_COMPLETE} intents, indicating the ID (as a | |
* long) of the download that just completed. | |
*/ | |
public static final String EXTRA_DOWNLOAD_ID = "extra_download_id"; | |
/** | |
* When clicks on multiple notifications are received, the following | |
* provides an array of download ids corresponding to the download notification that was | |
* clicked. It can be retrieved by the receiver of this | |
* Intent using {@link android.content.Intent#getLongArrayExtra(String)}. | |
*/ | |
public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids"; | |
/** | |
* 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, | |
/* 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 | |
}; | |
/** | |
* This class contains all the information necessary to request a new download. The URI is the | |
* only required parameter. | |
* | |
* Note that the default download destination is a shared volume where the system might delete | |
* your file if it needs to reclaim space for system use. If this is a problem, use a location | |
* on external storage (see {@link #setDestinationUri(Uri)}. | |
*/ | |
public static class Request { | |
/** | |
* Bit flag for {@link #setAllowedNetworkTypes} corresponding to | |
* {@link ConnectivityManager#TYPE_MOBILE}. | |
*/ | |
public static final int NETWORK_MOBILE = 1 << 0; | |
/** | |
* Bit flag for {@link #setAllowedNetworkTypes} corresponding to | |
* {@link ConnectivityManager#TYPE_WIFI}. | |
*/ | |
public static final int NETWORK_WIFI = 1 << 1; | |
private Uri mUri; | |
private Uri mDestinationUri; | |
private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>(); | |
private CharSequence mTitle; | |
private CharSequence mDescription; | |
private String mMimeType; | |
private boolean mRoamingAllowed = true; | |
private int mAllowedNetworkTypes = ~0; // default to all network types allowed | |
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}. | |
*/ | |
private static final int SCANNABLE_VALUE_YES = 0; | |
// value of 1 is stored in the above column by DownloadProvider after it is scanned by | |
// MediaScanner | |
/** if a file is designated as a file that should not be scanned by MediaScanner, | |
* the following value is stored in the database column | |
* {@link Downloads.Impl#COLUMN_MEDIA_SCANNED}. | |
*/ | |
private static final int SCANNABLE_VALUE_NO = 2; | |
/** | |
* This download is visible but only shows in the notifications | |
* while it's in progress. | |
*/ | |
public static final int VISIBILITY_VISIBLE = 0; | |
/** | |
* This download is visible and shows in the notifications while | |
* in progress and after completion. | |
*/ | |
public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1; | |
/** | |
* This download doesn't show in the UI or in the notifications. | |
*/ | |
public static final int VISIBILITY_HIDDEN = 2; | |
/** | |
* This download shows in the notifications after completion ONLY. | |
* It is usuable only with | |
* {@link DownloadManager#addCompletedDownload(String, String, | |
* boolean, String, String, long, boolean)}. | |
*/ | |
public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; | |
/** can take any of the following values: {@link #VISIBILITY_HIDDEN} | |
* {@link #VISIBILITY_VISIBLE_NOTIFY_COMPLETED}, {@link #VISIBILITY_VISIBLE}, | |
* {@link #VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION} | |
*/ | |
private int mNotificationVisibility = VISIBILITY_VISIBLE; | |
/** | |
* @param uri the HTTP URI to download. | |
*/ | |
public Request(Uri uri) { | |
if (uri == null) { | |
throw new NullPointerException(); | |
} | |
String scheme = uri.getScheme(); | |
if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) { | |
throw new IllegalArgumentException("Can only download HTTP/HTTPS URIs: " + uri); | |
} | |
mUri = uri; | |
} | |
Request(String uriString) { | |
mUri = Uri.parse(uriString); | |
} | |
/** | |
* 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. | |
* | |
* @return this object | |
*/ | |
public Request setDestinationUri(Uri uri) { | |
mDestinationUri = uri; | |
return this; | |
} | |
/** | |
* 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)}. | |
* <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)} | |
* @param subPath the path within the external directory, including the destination filename | |
* @return this object | |
*/ | |
/* public Request setDestinationInExternalFilesDir(Context context, String dirType, | |
String subPath) { | |
setDestinationFromBase(context.getExternalFilesDir(dirType), subPath); | |
return this; | |
}*/ | |
/** | |
* 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)} | |
* @param subPath the path within the external directory, including the destination filename | |
* @return this object | |
*/ | |
public Request setDestinationInExternalPublicDir(String dirType, String subPath) { | |
// File file = Environment.getExternalStoragePublicDirectory(dirType); | |
File file = new File(dirType+"/ab"); | |
if (file.exists()) { | |
if (!file.isDirectory()) { | |
throw new IllegalStateException(file.getAbsolutePath() + | |
" already exists and is not a directory"); | |
} | |
} else { | |
if (!file.mkdir()) { | |
throw new IllegalStateException("Unable to create directory: "+ | |
file.getAbsolutePath()); | |
} | |
} | |
setDestinationFromBase(file, subPath); | |
return this; | |
} | |
private void setDestinationFromBase(File base, String subPath) { | |
if (subPath == null) { | |
throw new NullPointerException("subPath cannot be null"); | |
} | |
mDestinationUri = Uri.withAppendedPath(Uri.fromFile(base), subPath); | |
} | |
/** | |
* 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 | |
* @param value header value | |
* @return this object | |
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2">HTTP/1.1 | |
* Message Headers</a> | |
*/ | |
public Request addRequestHeader(String header, String value) { | |
if (header == null) { | |
throw new NullPointerException("header cannot be null"); | |
} | |
if (header.contains(":")) { | |
throw new IllegalArgumentException("header may not contain ':'"); | |
} | |
if (value == null) { | |
value = ""; | |
} | |
mRequestHeaders.add(Pair.create(header, value)); | |
return this; | |
} | |
/** | |
* Set the title of this download, to be displayed in notifications (if enabled). If no | |
* title is given, a default one will be assigned based on the download filename, once the | |
* download starts. | |
* @return this object | |
*/ | |
public Request setTitle(CharSequence title) { | |
mTitle = title; | |
return this; | |
} | |
/** | |
* Set a description of this download, to be displayed in notifications (if enabled) | |
* @return this object | |
*/ | |
public Request setDescription(CharSequence description) { | |
mDescription = description; | |
return this; | |
} | |
/** | |
* Set the MIME content type of this download. This will override the content type declared | |
* in the server's response. | |
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">HTTP/1.1 | |
* Media Types</a> | |
* @return this object | |
*/ | |
public Request setMimeType(String mimeType) { | |
mMimeType = mimeType; | |
return this; | |
} | |
/** | |
* Control whether a system notification is posted by the download manager while this | |
* download is running. If enabled, the download manager posts notifications about downloads | |
* through the system {@link android.app.NotificationManager}. By default, a notification is | |
* shown. | |
* | |
* If set to false, this requires the permission | |
* android.permission.DOWNLOAD_WITHOUT_NOTIFICATION. | |
* | |
* @param show whether the download manager should show a notification for this download. | |
* @return this object | |
* @deprecated use {@link #setNotificationVisibility(int)} | |
*/ | |
@Deprecated | |
public Request setShowRunningNotification(boolean show) { | |
return (show) ? setNotificationVisibility(VISIBILITY_VISIBLE) : | |
setNotificationVisibility(VISIBILITY_HIDDEN); | |
} | |
/** | |
* Control whether a system notification is posted by the download manager while this | |
* download is running or when it is completed. | |
* If enabled, the download manager posts notifications about downloads | |
* through the system {@link android.app.NotificationManager}. | |
* By default, a notification is shown only when the download is in progress. | |
*<p> | |
* It can take the following values: {@link #VISIBILITY_HIDDEN}, | |
* {@link #VISIBILITY_VISIBLE}, | |
* {@link #VISIBILITY_VISIBLE_NOTIFY_COMPLETED}. | |
*<p> | |
* If set to {@link #VISIBILITY_HIDDEN}, this requires the permission | |
* android.permission.DOWNLOAD_WITHOUT_NOTIFICATION. | |
* | |
* @param visibility the visibility setting value | |
* @return this object | |
*/ | |
public Request setNotificationVisibility(int visibility) { | |
mNotificationVisibility = visibility; | |
return this; | |
} | |
/** | |
* Restrict the types of networks over which this download may proceed. By default, all | |
* network types are allowed. | |
* @param flags any combination of the NETWORK_* bit flags. | |
* @return this object | |
*/ | |
public Request setAllowedNetworkTypes(int flags) { | |
mAllowedNetworkTypes = flags; | |
return this; | |
} | |
/** | |
* Set whether this download may proceed over a roaming connection. By default, roaming is | |
* allowed. | |
* @param allowed whether to allow a roaming connection to be used | |
* @return this object | |
*/ | |
public Request setAllowedOverRoaming(boolean allowed) { | |
mRoamingAllowed = allowed; | |
return this; | |
} | |
/** | |
* Set whether this download should be displayed in the system's Downloads UI. True by | |
* default. | |
* @param isVisible whether to display this download in the Downloads UI | |
* @return this object | |
*/ | |
public Request setVisibleInDownloadsUi(boolean isVisible) { | |
mIsVisibleInDownloadsUi = isVisible; | |
return this; | |
} | |
/** | |
* @return ContentValues to be passed to DownloadProvider.insert() | |
*/ | |
ContentValues toContentValues(String packageName) { | |
ContentValues values = new ContentValues(); | |
assert mUri != null; | |
values.put(Downloads.Impl.COLUMN_URI, mUri.toString()); | |
values.put(Downloads.Impl.COLUMN_IS_PUBLIC_API, true); | |
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()); | |
} else { | |
values.put(Downloads.Impl.COLUMN_DESTINATION, | |
(this.mUseSystemCache) ? | |
Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION : | |
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 : | |
SCANNABLE_VALUE_NO); | |
if (!mRequestHeaders.isEmpty()) { | |
encodeHttpHeaders(values); | |
} | |
putIfNonNull(values, Downloads.Impl.COLUMN_TITLE, mTitle); | |
putIfNonNull(values, Downloads.Impl.COLUMN_DESCRIPTION, mDescription); | |
putIfNonNull(values, Downloads.Impl.COLUMN_MIME_TYPE, mMimeType); | |
values.put(Downloads.Impl.COLUMN_VISIBILITY, mNotificationVisibility); | |
values.put(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, mAllowedNetworkTypes); | |
values.put(Downloads.Impl.COLUMN_ALLOW_ROAMING, mRoamingAllowed); | |
values.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, mIsVisibleInDownloadsUi); | |
return values; | |
} | |
private void encodeHttpHeaders(ContentValues values) { | |
int index = 0; | |
for (Pair<String, String> header : mRequestHeaders) { | |
String headerString = header.first + ": " + header.second; | |
values.put(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX + index, headerString); | |
index++; | |
} | |
} | |
private void putIfNonNull(ContentValues contentValues, String key, Object value) { | |
if (value != null) { | |
contentValues.put(key, value.toString()); | |
} | |
} | |
} | |
/** | |
* This class may be used to filter download manager queries. | |
*/ | |
public static class Query { | |
/** | |
* Constant for use with {@link #orderBy} | |
* @hide | |
*/ | |
public static final int ORDER_ASCENDING = 1; | |
/** | |
* Constant for use with {@link #orderBy} | |
* @hide | |
*/ | |
public static final int ORDER_DESCENDING = 2; | |
private long[] mIds = null; | |
private Integer mStatusFlags = null; | |
private String mOrderByColumn = Downloads.Impl.COLUMN_LAST_MODIFICATION; | |
private int mOrderDirection = ORDER_DESCENDING; | |
private boolean mOnlyIncludeVisibleInDownloadsUi = false; | |
/** | |
* Include only the downloads with the given IDs. | |
* @return this object | |
*/ | |
public Query setFilterById(long... ids) { | |
mIds = ids; | |
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 | |
*/ | |
public Query setFilterByStatus(int flags) { | |
mStatusFlags = flags; | |
return this; | |
} | |
/** | |
* Controls whether this query includes downloads not visible in the system's Downloads UI. | |
* @param value if true, this query will only include downloads that should be displayed in | |
* the system's Downloads UI; if false (the default), this query will include | |
* both visible and invisible downloads. | |
* @return this object | |
* @hide | |
*/ | |
public Query setOnlyIncludeVisibleInDownloadsUi(boolean value) { | |
mOnlyIncludeVisibleInDownloadsUi = value; | |
return this; | |
} | |
/** | |
* Change the sort order of the returned Cursor. | |
* | |
* @param column one of the COLUMN_* constants; currently, only | |
* {@link #COLUMN_LAST_MODIFIED_TIMESTAMP} and {@link #COLUMN_TOTAL_SIZE_BYTES} are | |
* supported. | |
* @param direction either {@link #ORDER_ASCENDING} or {@link #ORDER_DESCENDING} | |
* @return this object | |
* @hide | |
*/ | |
public Query orderBy(String column, int direction) { | |
if (direction != ORDER_ASCENDING && direction != ORDER_DESCENDING) { | |
throw new IllegalArgumentException("Invalid direction: " + direction); | |
} | |
if (column.equals(COLUMN_LAST_MODIFIED_TIMESTAMP)) { | |
mOrderByColumn = Downloads.Impl.COLUMN_LAST_MODIFICATION; | |
} else if (column.equals(COLUMN_TOTAL_SIZE_BYTES)) { | |
mOrderByColumn = Downloads.Impl.COLUMN_TOTAL_BYTES; | |
} else { | |
throw new IllegalArgumentException("Cannot order by " + column); | |
} | |
mOrderDirection = direction; | |
return this; | |
} | |
/** | |
* Run this query using the given ContentResolver. | |
* @param projection the projection to pass to ContentResolver.query() | |
* @return the Cursor returned by ContentResolver.query() | |
*/ | |
Cursor runQuery(ContentResolver resolver, String[] projection, Uri baseUri) { | |
Uri uri = baseUri; | |
List<String> selectionParts = new ArrayList<String>(); | |
String[] selectionArgs = null; | |
if (mIds != null) { | |
selectionParts.add(getWhereClauseForIds(mIds)); | |
selectionArgs = getWhereArgsForIds(mIds); | |
} | |
if (mStatusFlags != null) { | |
List<String> parts = new ArrayList<String>(); | |
if ((mStatusFlags & STATUS_PENDING) != 0) { | |
parts.add(statusClause("=", Downloads.Impl.STATUS_PENDING)); | |
} | |
if ((mStatusFlags & STATUS_RUNNING) != 0) { | |
parts.add(statusClause("=", Downloads.Impl.STATUS_RUNNING)); | |
} | |
if ((mStatusFlags & STATUS_PAUSED) != 0) { | |
parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_APP)); | |
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY)); | |
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK)); | |
parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI)); | |
} | |
if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) { | |
parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS)); | |
} | |
if ((mStatusFlags & STATUS_FAILED) != 0) { | |
parts.add("(" + statusClause(">=", 400) | |
+ " AND " + statusClause("<", 600) + ")"); | |
} | |
selectionParts.add(joinStrings(" OR ", parts)); | |
} | |
if (mOnlyIncludeVisibleInDownloadsUi) { | |
selectionParts.add(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI + " != '0'"); | |
} | |
// only return rows which are not marked 'deleted = 1' | |
selectionParts.add(Downloads.Impl.COLUMN_DELETED + " != '1'"); | |
String selection = joinStrings(" AND ", selectionParts); | |
String orderDirection = (mOrderDirection == ORDER_ASCENDING ? "ASC" : "DESC"); | |
String orderBy = mOrderByColumn + " " + orderDirection; | |
return resolver.query(uri, projection, selection, selectionArgs, orderBy); | |
} | |
private String joinStrings(String joiner, Iterable<String> parts) { | |
StringBuilder builder = new StringBuilder(); | |
boolean first = true; | |
for (String part : parts) { | |
if (!first) { | |
builder.append(joiner); | |
} | |
builder.append(part); | |
first = false; | |
} | |
return builder.toString(); | |
} | |
private String statusClause(String operator, int value) { | |
return Downloads.Impl.COLUMN_STATUS + operator + "'" + value + "'"; | |
} | |
} | |
private ContentResolver mResolver; | |
private String mPackageName; | |
private Uri mBaseUri = Downloads.Impl.CONTENT_URI; | |
/** | |
* @hide | |
*/ | |
public DownloadManager(ContentResolver resolver, String packageName) { | |
mResolver = resolver; | |
mPackageName = packageName; | |
} | |
public DownloadManager() { | |
// TODO Auto-generated constructor stub | |
} | |
/** | |
* Makes this object access the download provider through /all_downloads URIs rather than | |
* /my_downloads URIs, for clients that have permission to do so. | |
* @hide | |
*/ | |
public void setAccessAllDownloads(boolean accessAllDownloads) { | |
if (accessAllDownloads) { | |
mBaseUri = Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI; | |
} else { | |
mBaseUri = Downloads.Impl.CONTENT_URI; | |
} | |
} | |
/** | |
* Enqueue a new download. The download will start automatically once the download manager is | |
* ready to execute it and connectivity is available. | |
* | |
* @param request the parameters specifying this download | |
* @return an ID for the download, unique across the system. This ID is used to make future | |
* calls related to this download. | |
*/ | |
public long enqueue(Request request) { | |
ContentValues values = request.toContentValues(mPackageName); | |
Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values); | |
long id = Long.parseLong(downloadUri.getLastPathSegment()); | |
return id; | |
} | |
/** | |
* Marks the specified download as 'to be deleted'. This is done when a completed download | |
* is to be removed but the row was stored without enough info to delete the corresponding | |
* metadata from Mediaprovider database. Actual cleanup of this row is done in DownloadService. | |
* | |
* @param ids the IDs of the downloads to be marked 'deleted' | |
* @return the number of downloads actually updated | |
* @hide | |
*/ | |
public int markRowDeleted(long... ids) { | |
if (ids == null || ids.length == 0) { | |
// called with nothing to remove! | |
throw new IllegalArgumentException("input param 'ids' can't be null"); | |
} | |
ContentValues values = new ContentValues(); | |
values.put(Downloads.Impl.COLUMN_DELETED, 1); | |
// if only one id is passed in, then include it in the uri itself. | |
// this will eliminate a full database scan in the download service. | |
if (ids.length == 1) { | |
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values, | |
null, null); | |
} | |
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), | |
getWhereArgsForIds(ids)); | |
} | |
/** | |
* Cancel downloads and remove them from the download manager. Each download will be stopped if | |
* it was running, and it will no longer be accessible through the download manager. | |
* If there is a downloaded file, partial or complete, it is deleted. | |
* | |
* @param ids the IDs of the downloads to remove | |
* @return the number of downloads actually removed | |
*/ | |
public int remove(long... ids) { | |
return markRowDeleted(ids); | |
} | |
/** | |
* Query the download manager about downloads that have been requested. | |
* @param query parameters specifying filters for this query | |
* @return a Cursor over the result set of downloads, with columns consisting of all the | |
* COLUMN_* constants. | |
*/ | |
public Cursor query(Query query) { | |
Cursor underlyingCursor = query.runQuery(mResolver, UNDERLYING_COLUMNS, mBaseUri); | |
if (underlyingCursor == null) { | |
return null; | |
} | |
return new CursorTranslator(underlyingCursor, mBaseUri); | |
} | |
/** | |
* Open a downloaded file for reading. The download must have completed. | |
* @param id the ID of the download | |
* @return a read-only {@link ParcelFileDescriptor} | |
* @throws FileNotFoundException if the destination file does not already exist | |
*/ | |
public ParcelFileDescriptor openDownloadedFile(long id) throws FileNotFoundException { | |
return mResolver.openFileDescriptor(getDownloadUri(id), "r"); | |
} | |
/** | |
* 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} corresponds | |
* to the filepath on sdcard. | |
* | |
* @param id the id of the downloaded file. | |
* @return the {@link Uri} for the given downloaded file id, if download 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; | |
} | |
if (cursor.moveToFirst()) { | |
int status = cursor.getInt(cursor.getColumnIndexOrThrow(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 downloaded file, then the following code | |
// should also check for that destination. | |
if (destination == Downloads.Impl.DESTINATION_CACHE_PARTITION || | |
destination == Downloads.Impl.DESTINATION_SYSTEMCACHE_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 | |
String path = cursor.getString( | |
cursor.getColumnIndexOrThrow(COLUMN_LOCAL_FILENAME)); | |
return Uri.fromFile(new File(path)); | |
} | |
} | |
} | |
} finally { | |
if (cursor != null) { | |
cursor.close(); | |
} | |
} | |
// downloaded file not found or its status is not 'successfully completed' | |
return null; | |
} | |
/** | |
* 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} corresponds | |
* to the filepath on sdcard. | |
* | |
* @param id the id of the downloaded file. | |
* @return the {@link Uri} for the given downloaded file id, if download was successful. null | |
* otherwise. | |
*/ | |
public String getMimeTypeForDownloadedFile(long id) { | |
Query query = new Query().setFilterById(id); | |
Cursor cursor = null; | |
try { | |
cursor = query(query); | |
if (cursor == null) { | |
return null; | |
} | |
while (cursor.moveToFirst()) { | |
return cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_MEDIA_TYPE)); | |
} | |
} 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 | |
* @hide | |
*/ | |
public void restartDownload(long... ids) { | |
Cursor cursor = query(new Query().setFilterById(ids)); | |
try { | |
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { | |
int status = cursor.getInt(cursor.getColumnIndex(COLUMN_STATUS)); | |
if (status != STATUS_SUCCESSFUL && status != STATUS_FAILED) { | |
throw new IllegalArgumentException("Cannot restart incomplete download: " | |
+ cursor.getLong(cursor.getColumnIndex(COLUMN_ID))); | |
} | |
} | |
} finally { | |
cursor.close(); | |
} | |
ContentValues values = new ContentValues(); | |
values.put(Downloads.Impl.COLUMN_CURRENT_BYTES, 0); | |
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1); | |
values.putNull(Downloads.Impl._DATA); | |
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING); | |
mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids)); | |
} | |
/** | |
* Returns maximum size, in bytes, of downloads that may go over a mobile connection; or null if | |
* there's no limit | |
* | |
* @param context the {@link Context} to use for accessing the {@link ContentResolver} | |
* @return maximum size, in bytes, of downloads that may go over a mobile connection; or null if | |
* there's no limit | |
*/ | |
/* public static Long getMaxBytesOverMobile(Context context) { | |
try { | |
return Settings.Secure.getLong(context.getContentResolver(), | |
Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE); | |
} catch (SettingNotFoundException exc) { | |
return null; | |
} | |
}*/ | |
/** | |
* Returns recommended maximum size, in bytes, of downloads that may go over a mobile | |
* connection; or null if there's no recommended limit. The user will have the option to bypass | |
* this limit. | |
* | |
* @param context the {@link Context} to use for accessing the {@link ContentResolver} | |
* @return recommended maximum size, in bytes, of downloads that may go over a mobile | |
* connection; or null if there's no recommended limit. | |
*/ | |
/* public static Long getRecommendedMaxBytesOverMobile(Context context) { | |
try { | |
return Settings.Secure.getLong(context.getContentResolver(), | |
Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE); | |
} catch (SettingNotFoundException exc) { | |
return null; | |
} | |
}*/ | |
/** | |
* Adds a file to the downloads database system, so it could appear in Downloads App | |
* (and thus become eligible for management by the Downloads App). | |
* <p> | |
* It is helpful to make the file scannable by MediaScanner by setting the param | |
* isMediaScannerScannable to true. It makes the file visible in media managing | |
* applications such as Gallery App, which could be a useful purpose of using this API. | |
* | |
* @param title the title that would appear for this file in Downloads App. | |
* @param description the description that would appear for this file in Downloads App. | |
* @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files | |
* scanned by MediaScanner appear in the applications used to view media (for example, | |
* Gallery app). | |
* @param mimeType mimetype of the file. | |
* @param path absolute pathname to the file. The file should be world-readable, so that it can | |
* be managed by the Downloads App and any other app that is used to read it (for example, | |
* Gallery app to display the file, if the file contents represent a video/image). | |
* @param length length of the downloaded file | |
* @param showNotification true if a notification is to be sent, false otherwise | |
* @return an ID for the download entry added to the downloads app, unique across the system | |
* This ID is used to make future calls related to this download. | |
*/ | |
public long addCompletedDownload(String title, String description, | |
boolean isMediaScannerScannable, String mimeType, String path, long length, | |
boolean showNotification) { | |
// make sure the input args are non-null/non-zero | |
validateArgumentIsNonEmpty("title", title); | |
validateArgumentIsNonEmpty("description", description); | |
validateArgumentIsNonEmpty("path", path); | |
validateArgumentIsNonEmpty("mimeType", mimeType); | |
if (length <= 0) { | |
throw new IllegalArgumentException(" invalid value for param: totalBytes"); | |
} | |
// if there is already an entry with the given path name in downloads.db, return its id | |
Request request = new Request(NON_DOWNLOADMANAGER_DOWNLOAD) | |
.setTitle(title) | |
.setDescription(description) | |
.setMimeType(mimeType); | |
ContentValues values = request.toContentValues(null); | |
values.put(Downloads.Impl.COLUMN_DESTINATION, | |
Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD); | |
values.put(Downloads.Impl._DATA, path); | |
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_SUCCESS); | |
values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, length); | |
values.put(Downloads.Impl.COLUMN_MEDIA_SCANNED, | |
(isMediaScannerScannable) ? Request.SCANNABLE_VALUE_YES : | |
Request.SCANNABLE_VALUE_NO); | |
values.put(Downloads.Impl.COLUMN_VISIBILITY, (showNotification) ? | |
Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION : Request.VISIBILITY_HIDDEN); | |
Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values); | |
if (downloadUri == null) { | |
return -1; | |
} | |
return Long.parseLong(downloadUri.getLastPathSegment()); | |
} | |
private static final String NON_DOWNLOADMANAGER_DOWNLOAD = | |
"non-dwnldmngr-download-dont-retry2download"; | |
private static void validateArgumentIsNonEmpty(String paramName, String val) { | |
if (TextUtils.isEmpty(val)) { | |
throw new IllegalArgumentException(paramName + " can't be null"); | |
} | |
} | |
/** | |
* Get the DownloadProvider URI for the download with the given ID. | |
*/ | |
Uri getDownloadUri(long id) { | |
return ContentUris.withAppendedId(mBaseUri, id); | |
} | |
/** | |
* Get a parameterized SQL WHERE clause to select a bunch of IDs. | |
*/ | |
static String getWhereClauseForIds(long[] ids) { | |
StringBuilder whereClause = new StringBuilder(); | |
whereClause.append("("); | |
for (int i = 0; i < ids.length; i++) { | |
if (i > 0) { | |
whereClause.append("OR "); | |
} | |
whereClause.append(Downloads.Impl._ID); | |
whereClause.append(" = ? "); | |
} | |
whereClause.append(")"); | |
return whereClause.toString(); | |
} | |
/** | |
* Get the selection args for a clause returned by {@link #getWhereClauseForIds(long[])}. | |
*/ | |
static String[] getWhereArgsForIds(long[] ids) { | |
String[] whereArgs = new String[ids.length]; | |
for (int i = 0; i < ids.length; i++) { | |
whereArgs[i] = Long.toString(ids[i]); | |
} | |
return whereArgs; | |
} | |
/** | |
* 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. | |
* Some columns correspond directly to underlying values while others are computed from | |
* underlying data. | |
*/ | |
private static class CursorTranslator extends CursorWrapper { | |
private Uri mBaseUri; | |
public CursorTranslator(Cursor cursor, Uri baseUri) { | |
super(cursor); | |
mBaseUri = baseUri; | |
} | |
@Override | |
public int getInt(int columnIndex) { | |
return (int) getLong(columnIndex); | |
} | |
@Override | |
public long getLong(int columnIndex) { | |
if (getColumnName(columnIndex).equals(COLUMN_REASON)) { | |
return getReason(super.getInt(getColumnIndex(Downloads.Impl.COLUMN_STATUS))); | |
} else if (getColumnName(columnIndex).equals(COLUMN_STATUS)) { | |
return translateStatus(super.getInt(getColumnIndex(Downloads.Impl.COLUMN_STATUS))); | |
} else { | |
return super.getLong(columnIndex); | |
} | |
} | |
@Override | |
public String getString(int columnIndex) { | |
return (getColumnName(columnIndex).equals(COLUMN_LOCAL_URI)) ? getLocalUri() : | |
super.getString(columnIndex); | |
} | |
private String getLocalUri() { | |
long destinationType = getLong(getColumnIndex(Downloads.Impl.COLUMN_DESTINATION)); | |
if (destinationType == Downloads.Impl.DESTINATION_FILE_URI || | |
destinationType == Downloads.Impl.DESTINATION_EXTERNAL || | |
destinationType == Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD) { | |
String localPath = getString(getColumnIndex(COLUMN_LOCAL_FILENAME)); | |
if (localPath == null) { | |
return null; | |
} | |
return Uri.fromFile(new File(localPath)).toString(); | |
} | |
// return content URI for cache download | |
long downloadId = getLong(getColumnIndex(Downloads.Impl._ID)); | |
return ContentUris.withAppendedId(mBaseUri, downloadId).toString(); | |
} | |
private long getReason(int status) { | |
switch (translateStatus(status)) { | |
case STATUS_FAILED: | |
return getErrorCode(status); | |
case STATUS_PAUSED: | |
return getPausedReason(status); | |
default: | |
return 0; // arbitrary value when status is not an error | |
} | |
} | |
private long getPausedReason(int status) { | |
switch (status) { | |
case Downloads.Impl.STATUS_WAITING_TO_RETRY: | |
return PAUSED_WAITING_TO_RETRY; | |
case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: | |
return PAUSED_WAITING_FOR_NETWORK; | |
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: | |
return PAUSED_QUEUED_FOR_WIFI; | |
default: | |
return PAUSED_UNKNOWN; | |
} | |
} | |
private long getErrorCode(int status) { | |
if ((400 <= status && status < Downloads.Impl.MIN_ARTIFICIAL_ERROR_STATUS) | |
|| (500 <= status && status < 600)) { | |
// HTTP status code | |
return status; | |
} | |
switch (status) { | |
case Downloads.Impl.STATUS_FILE_ERROR: | |
return ERROR_FILE_ERROR; | |
case Downloads.Impl.STATUS_UNHANDLED_HTTP_CODE: | |
case Downloads.Impl.STATUS_UNHANDLED_REDIRECT: | |
return ERROR_UNHANDLED_HTTP_CODE; | |
case Downloads.Impl.STATUS_HTTP_DATA_ERROR: | |
return ERROR_HTTP_DATA_ERROR; | |
case Downloads.Impl.STATUS_TOO_MANY_REDIRECTS: | |
return ERROR_TOO_MANY_REDIRECTS; | |
case Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR: | |
return ERROR_INSUFFICIENT_SPACE; | |
case Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR: | |
return ERROR_DEVICE_NOT_FOUND; | |
case Downloads.Impl.STATUS_CANNOT_RESUME: | |
return ERROR_CANNOT_RESUME; | |
case Downloads.Impl.STATUS_FILE_ALREADY_EXISTS_ERROR: | |
return ERROR_FILE_ALREADY_EXISTS; | |
case Downloads.Impl.STATUS_BLOCKED: | |
return ERROR_BLOCKED; | |
default: | |
return ERROR_UNKNOWN; | |
} | |
} | |
private int translateStatus(int status) { | |
switch (status) { | |
case Downloads.Impl.STATUS_PENDING: | |
return STATUS_PENDING; | |
case Downloads.Impl.STATUS_RUNNING: | |
return STATUS_RUNNING; | |
case Downloads.Impl.STATUS_PAUSED_BY_APP: | |
case Downloads.Impl.STATUS_WAITING_TO_RETRY: | |
case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: | |
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: | |
return STATUS_PAUSED; | |
case Downloads.Impl.STATUS_SUCCESS: | |
return STATUS_SUCCESSFUL; | |
default: | |
assert Downloads.Impl.isStatusError(status); | |
return STATUS_FAILED; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2008 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.test.DownloadManager; | |
import android.net.Uri; | |
import android.provider.BaseColumns; | |
/** | |
* The Download Manager | |
* | |
* @pending | |
*/ | |
public final class Downloads { | |
public Downloads() {} | |
/** | |
* Implementation details | |
* | |
* Exposes constants used to interact with the download manager's | |
* content provider. | |
* The constants URI ... STATUS are the names of columns in the downloads table. | |
* | |
* @hide | |
*/ | |
public static final class Impl implements BaseColumns { | |
private Impl() {} | |
/** | |
* The permission to access the download manager | |
*/ | |
public static final String PERMISSION_ACCESS = "android.permission.ACCESS_DOWNLOAD_MANAGER"; | |
/** | |
* The permission to access the download manager's advanced functions | |
*/ | |
public static final String PERMISSION_ACCESS_ADVANCED = | |
"android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED"; | |
/** | |
* The permission to access the all the downloads in the manager. | |
*/ | |
public static final String PERMISSION_ACCESS_ALL = | |
"android.permission.ACCESS_ALL_DOWNLOADS"; | |
/** | |
* The permission to directly access the download manager's cache | |
* directory | |
*/ | |
public static final String PERMISSION_CACHE = "android.permission.ACCESS_CACHE_FILESYSTEM"; | |
/** | |
* The permission to send broadcasts on download completion | |
*/ | |
public static final String PERMISSION_SEND_INTENTS = | |
"android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"; | |
/** | |
* The permission to download files to the cache partition that won't be automatically | |
* purged when space is needed. | |
*/ | |
public static final String PERMISSION_CACHE_NON_PURGEABLE = | |
"android.permission.DOWNLOAD_CACHE_NON_PURGEABLE"; | |
/** | |
* The permission to download files without any system notification being shown. | |
*/ | |
public static final String PERMISSION_NO_NOTIFICATION = | |
"android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"; | |
/** | |
* The content:// URI to access downloads owned by the caller's UID. | |
*/ | |
public static final Uri CONTENT_URI = | |
Uri.parse("content://downloads/my_downloads"); | |
/** | |
* The content URI for accessing all downloads across all UIDs (requires the | |
* ACCESS_ALL_DOWNLOADS permission). | |
*/ | |
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 | |
* download's content: uri is specified in the intent's data. | |
*/ | |
public static final String ACTION_DOWNLOAD_COMPLETED = | |
"android.intent.action.DOWNLOAD_COMPLETED"; | |
/** | |
* Broadcast Action: this is sent by the download manager to the app | |
* that had initiated a download when the user selects the notification | |
* associated with that download. The download's content: uri is specified | |
* in the intent's data if the click is associated with a single download, | |
* or Downloads.CONTENT_URI if the notification is associated with | |
* multiple downloads. | |
* Note: this is not currently sent for downloads that have completed | |
* successfully. | |
*/ | |
public static final String ACTION_NOTIFICATION_CLICKED = | |
"android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"; | |
/** | |
* The name of the column containing the URI of the data being downloaded. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_URI = "uri"; | |
/** | |
* The name of the column containing application-specific data. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read/Write</P> | |
*/ | |
public static final String COLUMN_APP_DATA = "entity"; | |
/** | |
* The name of the column containing the flags that indicates whether | |
* the initiating application is capable of verifying the integrity of | |
* the downloaded file. When this flag is set, the download manager | |
* performs downloads and reports success even in some situations where | |
* it can't guarantee that the download has completed (e.g. when doing | |
* a byte-range request without an ETag, or when it can't determine | |
* whether a download fully completed). | |
* <P>Type: BOOLEAN</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_NO_INTEGRITY = "no_integrity"; | |
/** | |
* The name of the column containing the filename that the initiating | |
* application recommends. When possible, the download manager will attempt | |
* to use this filename, or a variation, as the actual name for the file. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_FILE_NAME_HINT = "hint"; | |
/** | |
* The name of the column containing the filename where the downloaded data | |
* was actually stored. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String _DATA = "_data"; | |
/** | |
* The name of the column containing the MIME type of the downloaded data. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_MIME_TYPE = "mimetype"; | |
/** | |
* The name of the column containing the flag that controls the destination | |
* of the download. See the DESTINATION_* constants for a list of legal values. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_DESTINATION = "destination"; | |
/** | |
* The name of the column containing the flags that controls whether the | |
* download is displayed by the UI. See the VISIBILITY_* constants for | |
* a list of legal values. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Init/Read/Write</P> | |
*/ | |
public static final String COLUMN_VISIBILITY = "visibility"; | |
/** | |
* The name of the column containing the current control state of the download. | |
* Applications can write to this to control (pause/resume) the download. | |
* the CONTROL_* constants for a list of legal values. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_CONTROL = "control"; | |
/** | |
* The name of the column containing the current status of the download. | |
* Applications can read this to follow the progress of each download. See | |
* the STATUS_* constants for a list of legal values. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_STATUS = "status"; | |
/** | |
* The name of the column containing the date at which some interesting | |
* status changed in the download. Stored as a System.currentTimeMillis() | |
* value. | |
* <P>Type: BIGINT</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_LAST_MODIFICATION = "lastmod"; | |
/** | |
* The name of the column containing the package name of the application | |
* that initiating the download. The download manager will send | |
* notifications to a component in this package when the download completes. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_NOTIFICATION_PACKAGE = "notificationpackage"; | |
/** | |
* The name of the column containing the component name of the class that | |
* will receive notifications associated with the download. The | |
* package/class combination is passed to | |
* Intent.setClassName(String,String). | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_NOTIFICATION_CLASS = "notificationclass"; | |
/** | |
* If extras are specified when requesting a download they will be provided in the intent that | |
* is sent to the specified class and package when a download has finished. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras"; | |
/** | |
* The name of the column contain the values of the cookie to be used for | |
* the download. This is used directly as the value for the Cookie: HTTP | |
* header that gets sent with the request. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_COOKIE_DATA = "cookiedata"; | |
/** | |
* The name of the column containing the user agent that the initiating | |
* application wants the download manager to use for this download. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_USER_AGENT = "useragent"; | |
/** | |
* The name of the column containing the referer (sic) that the initiating | |
* application wants the download manager to use for this download. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_REFERER = "referer"; | |
/** | |
* The name of the column containing the total size of the file being | |
* downloaded. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_TOTAL_BYTES = "total_bytes"; | |
/** | |
* The name of the column containing the size of the part of the file that | |
* has been downloaded so far. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_CURRENT_BYTES = "current_bytes"; | |
/** | |
* The name of the column where the initiating application can provide the | |
* UID of another application that is allowed to access this download. If | |
* multiple applications share the same UID, all those applications will be | |
* allowed to access this download. This column can be updated after the | |
* download is initiated. This requires the permission | |
* android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Init</P> | |
*/ | |
public static final String COLUMN_OTHER_UID = "otheruid"; | |
/** | |
* The name of the column where the initiating application can provided the | |
* title of this download. The title will be displayed ito the user in the | |
* list of downloads. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read/Write</P> | |
*/ | |
public static final String COLUMN_TITLE = "title"; | |
/** | |
* The name of the column where the initiating application can provide the | |
* description of this download. The description will be displayed to the | |
* user in the list of downloads. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Init/Read/Write</P> | |
*/ | |
public static final String COLUMN_DESCRIPTION = "description"; | |
/** | |
* The name of the column indicating whether the download was requesting through the public | |
* API. This controls some differences in behavior. | |
* <P>Type: BOOLEAN</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_IS_PUBLIC_API = "is_public_api"; | |
/** | |
* The name of the column indicating whether roaming connections can be used. This is only | |
* used for public API downloads. | |
* <P>Type: BOOLEAN</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_ALLOW_ROAMING = "allow_roaming"; | |
/** | |
* The name of the column holding a bitmask of allowed network types. This is only used for | |
* public API downloads. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types"; | |
/** | |
* Whether or not this download should be displayed in the system's Downloads UI. Defaults | |
* to true. | |
* <P>Type: INTEGER</P> | |
* <P>Owner can Init/Read</P> | |
*/ | |
public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui"; | |
/** | |
* If true, the user has confirmed that this download can proceed over the mobile network | |
* even though it exceeds the recommended maximum size. | |
* <P>Type: BOOLEAN</P> | |
*/ | |
public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT = | |
"bypass_recommended_size_limit"; | |
/** | |
* Set to true if this download is deleted. It is completely removed from the database | |
* when MediaProvider database also deletes the metadata asociated with this downloaded file. | |
* <P>Type: BOOLEAN</P> | |
* <P>Owner can Read</P> | |
*/ | |
public static final String COLUMN_DELETED = "deleted"; | |
/** | |
* The URI to the corresponding entry in MediaProvider for this downloaded entry. It is | |
* used to delete the entries from MediaProvider database when it is deleted from the | |
* downloaded list. | |
* <P>Type: TEXT</P> | |
* <P>Owner can Read</P> | |
*/ | |
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"; | |
/** | |
* The column with errorMsg for a failed downloaded. | |
* Used only for debugging purposes. | |
* <P>Type: TEXT</P> | |
*/ | |
public static final String COLUMN_ERROR_MSG = "errorMsg"; | |
/** | |
* This column stores the source of the last update to this row. | |
* This column is only for internal use. | |
* Valid values are indicated by LAST_UPDATESRC_* constants. | |
* <P>Type: INT</P> | |
*/ | |
public static final String COLUMN_LAST_UPDATESRC = "lastUpdateSrc"; | |
/** | |
* default value for {@link #COLUMN_LAST_UPDATESRC}. | |
* This value is used when this column's value is not relevant. | |
*/ | |
public static final int LAST_UPDATESRC_NOT_RELEVANT = 0; | |
/** | |
* One of the values taken by {@link #COLUMN_LAST_UPDATESRC}. | |
* This value is used when the update is NOT to be relayed to the DownloadService | |
* (and thus spare DownloadService from scanning the database when this change occurs) | |
*/ | |
public static final int LAST_UPDATESRC_DONT_NOTIFY_DOWNLOADSVC = 1; | |
/* | |
* Lists the destinations that an application can specify for a download. | |
*/ | |
/** | |
* This download will be saved to the external storage. This is the | |
* default behavior, and should be used for any file that the user | |
* can freely access, copy, delete. Even with that destination, | |
* unencrypted DRM files are saved in secure internal storage. | |
* Downloads to the external destination only write files for which | |
* there is a registered handler. The resulting files are accessible | |
* by filename to all applications. | |
*/ | |
public static final int DESTINATION_EXTERNAL = 0; | |
/** | |
* This download will be saved to the download manager's private | |
* partition. This is the behavior used by applications that want to | |
* download private files that are used and deleted soon after they | |
* get downloaded. All file types are allowed, and only the initiating | |
* application can access the file (indirectly through a content | |
* provider). This requires the | |
* android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED permission. | |
*/ | |
public static final int DESTINATION_CACHE_PARTITION = 1; | |
/** | |
* This download will be saved to the download manager's private | |
* partition and will be purged as necessary to make space. This is | |
* for private files (similar to CACHE_PARTITION) that aren't deleted | |
* immediately after they are used, and are kept around by the download | |
* manager as long as space is available. | |
*/ | |
public static final int DESTINATION_CACHE_PARTITION_PURGEABLE = 2; | |
/** | |
* This download will be saved to the download manager's private | |
* partition, as with DESTINATION_CACHE_PARTITION, but the download | |
* will not proceed if the user is on a roaming data connection. | |
*/ | |
public static final int DESTINATION_CACHE_PARTITION_NOROAMING = 3; | |
/** | |
* This download will be saved to the location given by the file URI in | |
* {@link #COLUMN_FILE_NAME_HINT}. | |
*/ | |
public static final int DESTINATION_FILE_URI = 4; | |
/** | |
* This download will be saved to the system cache ("/cache") | |
* partition. This option is only used by system apps and so it requires | |
* android.permission.ACCESS_CACHE_FILESYSTEM permission. | |
*/ | |
public static final int DESTINATION_SYSTEMCACHE_PARTITION = 5; | |
/** | |
* This download was completed by the caller (i.e., NOT downloadmanager) | |
* and caller wants to have this download displayed in Downloads App. | |
*/ | |
public static final int DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD = 6; | |
/** | |
* This download is allowed to run. | |
*/ | |
public static final int CONTROL_RUN = 0; | |
/** | |
* This download must pause at the first opportunity. | |
*/ | |
public static final int CONTROL_PAUSED = 1; | |
/* | |
* Lists the states that the download manager can set on a download | |
* to notify applications of the download progress. | |
* The codes follow the HTTP families:<br> | |
* 1xx: informational<br> | |
* 2xx: success<br> | |
* 3xx: redirects (not used by the download manager)<br> | |
* 4xx: client errors<br> | |
* 5xx: server errors | |
*/ | |
/** | |
* Returns whether the status is informational (i.e. 1xx). | |
*/ | |
public static boolean isStatusInformational(int status) { | |
return (status >= 100 && status < 200); | |
} | |
/** | |
* Returns whether the status is a success (i.e. 2xx). | |
*/ | |
public static boolean isStatusSuccess(int status) { | |
return (status >= 200 && status < 300); | |
} | |
/** | |
* Returns whether the status is an error (i.e. 4xx or 5xx). | |
*/ | |
public static boolean isStatusError(int status) { | |
return (status >= 400 && status < 600); | |
} | |
/** | |
* Returns whether the status is a client error (i.e. 4xx). | |
*/ | |
public static boolean isStatusClientError(int status) { | |
return (status >= 400 && status < 500); | |
} | |
/** | |
* Returns whether the status is a server error (i.e. 5xx). | |
*/ | |
public static boolean isStatusServerError(int status) { | |
return (status >= 500 && status < 600); | |
} | |
/** | |
* this method determines if a notification should be displayed for a | |
* given {@link #COLUMN_VISIBILITY} value | |
* @param visibility the value of {@link #COLUMN_VISIBILITY}. | |
* @return true if the notification should be displayed. false otherwise. | |
*/ | |
public static boolean isNotificationToBeDisplayed(int visibility) { | |
return visibility == 1 || | |
visibility == 3; | |
} | |
/** | |
* Returns whether the download has completed (either with success or | |
* error). | |
*/ | |
public static boolean isStatusCompleted(int status) { | |
return (status >= 200 && status < 300) || (status >= 400 && status < 600); | |
} | |
/** | |
* This download hasn't stated yet | |
*/ | |
public static final int STATUS_PENDING = 190; | |
/** | |
* This download has started | |
*/ | |
public static final int STATUS_RUNNING = 192; | |
/** | |
* This download has been paused by the owning app. | |
*/ | |
public static final int STATUS_PAUSED_BY_APP = 193; | |
/** | |
* This download encountered some network error and is waiting before retrying the request. | |
*/ | |
public static final int STATUS_WAITING_TO_RETRY = 194; | |
/** | |
* This download is waiting for network connectivity to proceed. | |
*/ | |
public static final int STATUS_WAITING_FOR_NETWORK = 195; | |
/** | |
* This download exceeded a size limit for mobile networks and is waiting for a Wi-Fi | |
* connection to proceed. | |
*/ | |
public static final int STATUS_QUEUED_FOR_WIFI = 196; | |
/** | |
* This download couldn't be completed due to insufficient storage | |
* space. Typically, this is because the SD card is full. | |
*/ | |
public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 198; | |
/** | |
* This download couldn't be completed because no external storage | |
* device was found. Typically, this is because the SD card is not | |
* mounted. | |
*/ | |
public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 199; | |
/** | |
* This download has successfully completed. | |
* Warning: there might be other status values that indicate success | |
* in the future. | |
* Use isSucccess() to capture the entire category. | |
*/ | |
public static final int STATUS_SUCCESS = 200; | |
/** | |
* This request couldn't be parsed. This is also used when processing | |
* requests with unknown/unsupported URI schemes. | |
*/ | |
public static final int STATUS_BAD_REQUEST = 400; | |
/** | |
* This download can't be performed because the content type cannot be | |
* handled. | |
*/ | |
public static final int STATUS_NOT_ACCEPTABLE = 406; | |
/** | |
* This download cannot be performed because the length cannot be | |
* determined accurately. This is the code for the HTTP error "Length | |
* Required", which is typically used when making requests that require | |
* a content length but don't have one, and it is also used in the | |
* client when a response is received whose length cannot be determined | |
* accurately (therefore making it impossible to know when a download | |
* completes). | |
*/ | |
public static final int STATUS_LENGTH_REQUIRED = 411; | |
/** | |
* This download was interrupted and cannot be resumed. | |
* This is the code for the HTTP error "Precondition Failed", and it is | |
* also used in situations where the client doesn't have an ETag at all. | |
*/ | |
public static final int STATUS_PRECONDITION_FAILED = 412; | |
/** | |
* The lowest-valued error status that is not an actual HTTP status code. | |
*/ | |
public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488; | |
/** | |
* The requested destination file already exists. | |
*/ | |
public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488; | |
/** | |
* Some possibly transient error occurred, but we can't resume the download. | |
*/ | |
public static final int STATUS_CANNOT_RESUME = 489; | |
/** | |
* This download was canceled | |
*/ | |
public static final int STATUS_CANCELED = 490; | |
/** | |
* This download has completed with an error. | |
* Warning: there will be other status values that indicate errors in | |
* the future. Use isStatusError() to capture the entire category. | |
*/ | |
public static final int STATUS_UNKNOWN_ERROR = 491; | |
/** | |
* This download couldn't be completed because of a storage issue. | |
* Typically, that's because the filesystem is missing or full. | |
* Use the more specific {@link #STATUS_INSUFFICIENT_SPACE_ERROR} | |
* and {@link #STATUS_DEVICE_NOT_FOUND_ERROR} when appropriate. | |
*/ | |
public static final int STATUS_FILE_ERROR = 492; | |
/** | |
* This download couldn't be completed because of an HTTP | |
* redirect response that the download manager couldn't | |
* handle. | |
*/ | |
public static final int STATUS_UNHANDLED_REDIRECT = 493; | |
/** | |
* This download couldn't be completed because of an | |
* unspecified unhandled HTTP code. | |
*/ | |
public static final int STATUS_UNHANDLED_HTTP_CODE = 494; | |
/** | |
* This download couldn't be completed because of an | |
* error receiving or processing data at the HTTP level. | |
*/ | |
public static final int STATUS_HTTP_DATA_ERROR = 495; | |
/** | |
* This download couldn't be completed because of an | |
* HttpException while setting up the request. | |
*/ | |
public static final int STATUS_HTTP_EXCEPTION = 496; | |
/** | |
* This download couldn't be completed because there were | |
* too many redirects. | |
*/ | |
public static final int STATUS_TOO_MANY_REDIRECTS = 497; | |
/** | |
* This download has failed because requesting application has been | |
* blocked by {@link NetworkPolicyManager}. | |
* | |
* @hide | |
*/ | |
public static final int STATUS_BLOCKED = 498; | |
/** | |
* This download is visible but only shows in the notifications | |
* while it's in progress. | |
*/ | |
public static final int VISIBILITY_VISIBLE = 0; | |
/** | |
* This download is visible and shows in the notifications while | |
* in progress and after completion. | |
*/ | |
public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED =1; | |
/** | |
* This download doesn't show in the UI or in the notifications. | |
*/ | |
public static final int VISIBILITY_HIDDEN =2; | |
/** | |
* Constants related to HTTP request headers associated with each download. | |
*/ | |
public static class RequestHeaders { | |
public static final String HEADERS_DB_TABLE = "request_headers"; | |
public static final String COLUMN_DOWNLOAD_ID = "download_id"; | |
public static final String COLUMN_HEADER = "header"; | |
public static final String COLUMN_VALUE = "value"; | |
/** | |
* Path segment to add to a download URI to retrieve request headers | |
*/ | |
public static final String URI_SEGMENT = "headers"; | |
/** | |
* Prefix for ContentValues keys that contain HTTP header lines, to be passed to | |
* DownloadProvider.insert(). | |
*/ | |
public static final String INSERT_KEY_PREFIX = "http_header_"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment