Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android 2.3.3中使用下载管理器请求多次下载_Android_Download Manager - Fatal编程技术网

如何在Android 2.3.3中使用下载管理器请求多次下载

如何在Android 2.3.3中使用下载管理器请求多次下载,android,download-manager,Android,Download Manager,如何请求Android下载管理器同时下载多个文件。我还想知道每个文件的下载状态。请求第一个文件 然后,请求第二个 然后,请求第三个 根据需要继续 他们是否“同时”下载不是你的问题,你也无法控制。当DownloadManager决定下载它们时,它们将进行下载,可以同时下载,也可以不同时下载。公共类DownloadManager{ 1. Register listener for download complete IntentFilter intentFilter = new IntentFi

如何请求Android下载管理器同时下载多个文件。我还想知道每个文件的下载状态。

请求第一个文件

然后,请求第二个

然后,请求第三个

根据需要继续


他们是否“同时”下载不是你的问题,你也无法控制。当
DownloadManager
决定下载它们时,它们将进行下载,可以同时下载,也可以不同时下载。

公共类DownloadManager{
1. Register listener for download complete
  IntentFilter intentFilter = new IntentFilter(
            DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    registerReceiver(downloadReceiver, intentFilter);
2.Make request

Uri downloadUri = Uri.parse(entry.getValue());
            DownloadManager.Request request = new DownloadManager.Request(
                    downloadUri);

            request.setDestinationUri(path_to _file_store)));
            downloadManager.enqueue(request);
3.Check status in listener
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context arg0, Intent intent) {
        String action = intent.getAction();
        if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
            long downloadId = intent.getLongExtra(
                    DownloadManager.EXTRA_DOWNLOAD_ID, 0);
            System.out.println("download id=" + downloadId);
            CheckDwnloadStatus(downloadId);
        }
    }
};
private void CheckDwnloadStatus(long id) {

    // TODO Auto-generated method stub
    DownloadManager.Query query = new DownloadManager.Query();

    query.setFilterById(id);
    Cursor cursor = downloadManager.query(query);
    if (cursor.moveToFirst()) {
        int columnIndex = cursor
                .getColumnIndex(DownloadManager.COLUMN_STATUS);
        int status = cursor.getInt(columnIndex);
        int columnReason = cursor
                .getColumnIndex(DownloadManager.COLUMN_REASON);
        int reason = cursor.getInt(columnReason);

        switch (status) {
        case DownloadManager.STATUS_FAILED:
            String failedReason = "";
            switch (reason) {
            case DownloadManager.ERROR_CANNOT_RESUME:
                failedReason = "ERROR_CANNOT_RESUME";
                break;
            case DownloadManager.ERROR_DEVICE_NOT_FOUND:
                failedReason = "ERROR_DEVICE_NOT_FOUND";
                break;
            case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
                failedReason = "ERROR_FILE_ALREADY_EXISTS";
                break;
            case DownloadManager.ERROR_FILE_ERROR:
                failedReason = "ERROR_FILE_ERROR";
                break;
            case DownloadManager.ERROR_HTTP_DATA_ERROR:
                failedReason = "ERROR_HTTP_DATA_ERROR";
                break;
            case DownloadManager.ERROR_INSUFFICIENT_SPACE:
                failedReason = "ERROR_INSUFFICIENT_SPACE";
                break;
            case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
                failedReason = "ERROR_TOO_MANY_REDIRECTS";
                break;
            case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
                failedReason = "ERROR_UNHANDLED_HTTP_CODE";
                break;
            case DownloadManager.ERROR_UNKNOWN:
                failedReason = "ERROR_UNKNOWN";
                break;
            }

            Toast.makeText(this, "FAILED: " + failedReason,
                    Toast.LENGTH_LONG).show();
            break;
        case DownloadManager.STATUS_PAUSED:
            String pausedReason = "";

            switch (reason) {
            case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
                pausedReason = "PAUSED_QUEUED_FOR_WIFI";
                break;
            case DownloadManager.PAUSED_UNKNOWN:
                pausedReason = "PAUSED_UNKNOWN";
                break;
            case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
                pausedReason = "PAUSED_WAITING_FOR_NETWORK";
                break;
            case DownloadManager.PAUSED_WAITING_TO_RETRY:
                pausedReason = "PAUSED_WAITING_TO_RETRY";
                break;
            }

            Toast.makeText(this, "PAUSED: " + pausedReason,
                    Toast.LENGTH_LONG).show();
            break;
        case DownloadManager.STATUS_PENDING:
            Toast.makeText(this, "PENDING", Toast.LENGTH_LONG).show();
            break;
        case DownloadManager.STATUS_RUNNING:
            Toast.makeText(this, "RUNNING", Toast.LENGTH_LONG).show();
            break;
        case DownloadManager.STATUS_SUCCESSFUL:
            caluclateLoadingData();
            // Toast.makeText(this, "SUCCESSFUL", Toast.LENGTH_LONG).show();
            // GetFile();
            break;
        }
    }
}
私有静态最终字符串标记=“DownloadManager”

public final static String COLUMN\u ID=BaseColumns.\u ID;
公共最终静态字符串列\u TITLE=“TITLE”;
公共最终静态字符串列\u DESCRIPTION=“DESCRIPTION”;
公共最终静态字符串列_URI=“URI”;
公共最终静态字符串列\u MEDIA\u TYPE=“MEDIA\u TYPE”;
公共最终静态字符串列\u TOTAL\u SIZE\u BYTES=“TOTAL\u SIZE”;
公共最终静态字符串列\u LOCAL\u URI=“LOCAL\u URI”;
公共最终静态字符串列\u STATUS=“STATUS”;
公共最终静态字符串列\u REASON=“REASON”;
公共最终静态字符串列\u BYTES\u download\u SO\u FAR=“BYTES\u SO\u FAR”;
公共最终静态字符串列\u LAST\u MODIFIED\u TIMESTAMP=“LAST\u MODIFIED\u TIMESTAMP”;
公共静态最终字符串列\u MEDIAPROVIDER\u URI=“MEDIAPROVIDER\u URI”;
public final STATUS_PENDING=1
public final类下载{
/**
*@隐藏
*/
私有下载(){}
/**
*访问下载管理器的权限
*@隐藏。
*/
public static final String PERMISSION\u ACCESS=“android.PERMISSION.ACCESS\u DOWNLOAD\u MANAGER”;
/**
*访问下载管理器高级功能的权限
*@隐藏
*/
公共静态最终字符串权限\u访问\u高级=
“android.permission.ACCESS\u DOWNLOAD\u MANAGER\u ADVANCED”;
/**
*直接访问下载管理器缓存目录的权限
*@隐藏
*/
公共静态最终字符串权限\u CACHE=“android.PERMISSION.ACCESS\u CACHE\u文件系统”;
/**
*下载完成时发送广播的权限
*@隐藏
*/
公共静态最终字符串权限\u发送\u意图=
“android.permission.SEND\u DOWNLOAD\u COMPLETED\u INTENTS”;
/**
*提供程序中数据表的content://URI
*@隐藏
*/
公共静态最终Uri内容\u Uri=
解析content://downloads/my_downloads");
/**
*广播操作:由下载管理器发送到应用程序
*已在下载完成时启动下载的
*下载内容:uri在意图的数据中指定。
*@隐藏
*/
公共静态最终字符串操作\u下载\u完成=
“android.intent.action.DOWNLOAD_COMPLETED”;
/**
*广播操作:由下载管理器发送到应用程序
*当用户选择通知时已启动下载的
*与该下载关联。指定了下载的内容:uri
*在意图的数据中,如果单击与单个下载关联,
*或下载.CONTENT\u URI(如果通知与
*多次下载。
*注意:对于已完成的下载,当前不会发送此消息
*成功。
*@隐藏
*/
公共静态最终字符串操作\u通知\u已单击=
“android.intent.action.DOWNLOAD\u NOTIFICATION\u CLICKED”;
/**
*包含正在下载的数据的URI的列的名称。
*

类型:文本 *

所有者可以初始化/读取 *@隐藏 */ 公共静态最终字符串列_URI=“URI”; 公共静态最终字符串列\u APP\u DATA=“entity”; 公共静态最终字符串列\u NO\u INTEGRITY=“NO\u INTEGRITY”; 公共静态最终字符串列\u FILE\u NAME\u HINT=“HINT”; 公共静态最终字符串_DATA=“_DATA”; 公共静态最终字符串列\u MIME\u TYPE=“mimetype”; 公共静态最终字符串列\u DESTINATION=“DESTINATION”; 公共静态最终字符串列\u VISIBILITY=“VISIBILITY”; 公共静态最终字符串列\u CONTROL=“CONTROL”; 公共静态最终字符串列\u STATUS=“STATUS”; /** *列的名称,该列包含某个事件发生的日期 *下载中的状态已更改。存储为System.currentTimeMillis() *价值观。 *

类型:BIGINT

*

所有者可以阅读 *@隐藏 */ 公共静态最终字符串列\u LAST\u MODIFICATION=“lastmod”; /** *包含应用程序包名称的列的名称 *正在启动下载。下载管理器将发送 *下载完成时向此包中的组件发送通知。 *

类型:文本 *

所有者可以初始化/读取 *@隐藏 */ 公共静态最终字符串列\u NOTIFICATION\u PACKAGE=“notificationpackage”; 公共静态最终字符串列\u NOTIFICATION\u CLASS=“notificationclass”; 公共静态最终字符串列\u NOTIFICATION\u EXTRAS=“notificationextras”; 公共静态最终字符串列\u COOKIE\u DATA=“cookiedata”; 公共静态最终字符串列\u USER\u AGENT=“useragent”; 公共静态最终字符串列\u REFERER=“REFERER”; 公共静态最终字符串列\u TOTAL\u BYTES=“TOTAL\u BYTES”; 公共静态最终字符串列\u CURRENT\u BYTES=“CURRENT\u BYTES”; 公共静态最终字符串列\u OTHER\u UID=“otheruid”; 公共静态最终字符串列\u TITLE=“TITLE”; 公共静态最终字符串列\u DESCRIPTION=“DESCRIPTION”; 公共静态最终字符串列\u DELETED=“DELETED”; 公共静态最终整数目的地\外部=0; 公共静态最终int目的地\缓存\分区=1; 公共静态最终int目的地\缓存\分区\可购买=2; 公共静态最终int目的地\u缓存\u分区\u NOROAMING=3; 公共静态最终整数控制_RUN=0; 公共静态最终整数控制_=1; /** *返回状态是否为信息状态(即1xx)。 *@隐藏 */ 公共静态布尔ISStatusInformation(int状态){ 返回(状态>=100和状态<200); } 公共静态布尔值isStatusSuccess(int状态){ 返回

public final static String COLUMN_ID = BaseColumns._ID;

public final static String COLUMN_TITLE = "title";

public final static String COLUMN_DESCRIPTION = "description";

public final static String COLUMN_URI = "uri";

public final static String COLUMN_MEDIA_TYPE = "media_type";

public final static String COLUMN_TOTAL_SIZE_BYTES = "total_size";

public final static String COLUMN_LOCAL_URI = "local_uri";

public final static String COLUMN_STATUS = "status";

public final static String COLUMN_REASON = "reason";

public final static String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";

public final static String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";

public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";

public final static int STATUS_PENDING = 1 << 0;

public final static int STATUS_RUNNING = 1 << 1;

public final static int STATUS_PAUSED = 1 << 2;

public final static int STATUS_SUCCESSFUL = 1 << 3;

public final static int STATUS_FAILED = 1 << 4;

public final static int ERROR_UNKNOWN = 1000;

public final static int ERROR_FILE_ERROR = 1001;

public final static int ERROR_UNHANDLED_HTTP_CODE = 1002;

public final static int ERROR_HTTP_DATA_ERROR = 1004;

public final static int ERROR_TOO_MANY_REDIRECTS = 1005;

public final static int ERROR_INSUFFICIENT_SPACE = 1006;

public final static int ERROR_DEVICE_NOT_FOUND = 1007;

public final static int ERROR_CANNOT_RESUME = 1008;

public final static int ERROR_FILE_ALREADY_EXISTS = 1009;

public final static int PAUSED_WAITING_TO_RETRY = 1;

public final static int PAUSED_WAITING_FOR_NETWORK = 2;

public final static int PAUSED_QUEUED_FOR_WIFI = 3;

public final static int PAUSED_UNKNOWN = 4;

public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";

public final static String ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";

public final static String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";

public static final String EXTRA_DOWNLOAD_ID = "extra_download_id";

// this array must contain all public columns
private static final String[] COLUMNS = new String[] { COLUMN_ID,
        COLUMN_MEDIAPROVIDER_URI, COLUMN_TITLE, COLUMN_DESCRIPTION,
        COLUMN_URI, COLUMN_MEDIA_TYPE, COLUMN_TOTAL_SIZE_BYTES,
        COLUMN_LOCAL_URI, COLUMN_STATUS, COLUMN_REASON,
        COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP };

// columns to request from DownloadProvider
private static final String[] UNDERLYING_COLUMNS = new String[] {
        Downloads.Impl._ID, Downloads.Impl.COLUMN_MEDIAPROVIDER_URI,
        Downloads.COLUMN_TITLE, Downloads.COLUMN_DESCRIPTION,
        Downloads.COLUMN_URI, Downloads.COLUMN_MIME_TYPE,
        Downloads.COLUMN_TOTAL_BYTES, Downloads.COLUMN_STATUS,
        Downloads.COLUMN_CURRENT_BYTES, Downloads.COLUMN_LAST_MODIFICATION,
        Downloads.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));

public static class Request {

    public static final int NETWORK_MOBILE = 1 << 0;
    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 boolean mShowNotification = true;
    private String mMimeType;
    private boolean mRoamingAllowed = true;
    private int mAllowedNetworkTypes = ~0; // default to all network types
                                            // allowed
    private boolean mIsVisibleInDownloadsUi = true;

    /**
     * @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 URIs: " + uri);
        }
        mUri = uri;
    }


    public Request setDestinationUri(Uri uri) {
        mDestinationUri = uri;
        return this;
    }


    public Request setDestinationInExternalFilesDir(Context context,
            String dirType, String subPath) {
        setDestinationFromBase(context.getExternalFilesDir(dirType),
                subPath);
        return this;
    }


    public Request setDestinationInExternalPublicDir(String dirType,
            String subPath) {
        setDestinationFromBase(
                Environment.getExternalStoragePublicDirectory(dirType),
                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);
    }


    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;
    }


    public Request setTitle(CharSequence title) {
        mTitle = title;
        return this;
    }


    public Request setDescription(CharSequence description) {
        mDescription = description;
        return this;
    }


    public Request setMimeType(String mimeType) {
        mMimeType = mimeType;
        return this;
    }


    public Request setShowRunningNotification(boolean show) {
        mShowNotification = show;
        return this;
    }


    public Request setAllowedNetworkTypes(int flags) {
        mAllowedNetworkTypes = flags;
        return this;
    }


    public Request setAllowedOverRoaming(boolean allowed) {
        mRoamingAllowed = allowed;
        return this;
    }


    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.COLUMN_URI, mUri.toString());
        values.put(Downloads.Impl.COLUMN_IS_PUBLIC_API, true);
        values.put(Downloads.COLUMN_NOTIFICATION_PACKAGE, packageName);

        if (mDestinationUri != null) {
            values.put(Downloads.COLUMN_DESTINATION,
                    Downloads.Impl.DESTINATION_FILE_URI);
            values.put(Downloads.COLUMN_FILE_NAME_HINT,
                    mDestinationUri.toString());
        } else {
            values.put(Downloads.COLUMN_DESTINATION,
                    Downloads.DESTINATION_CACHE_PARTITION_PURGEABLE);
        }

        if (!mRequestHeaders.isEmpty()) {
            encodeHttpHeaders(values);
        }

        putIfNonNull(values, Downloads.COLUMN_TITLE, mTitle);
        putIfNonNull(values, Downloads.COLUMN_DESCRIPTION, mDescription);
        putIfNonNull(values, Downloads.COLUMN_MIME_TYPE, mMimeType);

        values.put(Downloads.COLUMN_VISIBILITY,
                mShowNotification ? Downloads.VISIBILITY_VISIBLE
                        : Downloads.VISIBILITY_HIDDEN);

        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.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.COLUMN_LAST_MODIFICATION;
        } else if (column.equals(COLUMN_TOTAL_SIZE_BYTES)) {
            mOrderByColumn = Downloads.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.STATUS_PENDING));
            }
            if ((mStatusFlags & STATUS_RUNNING) != 0) {
                parts.add(statusClause("=", Downloads.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.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.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;
}

/**
 * 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;
    }
}

public long enqueue(Request request) {
    ContentValues values = request.toContentValues(mPackageName);
    Uri downloadUri = mResolver.insert(Downloads.CONTENT_URI, values);
    long id = Long.parseLong(downloadUri.getLastPathSegment());
    return id;
}

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);
    return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
            getWhereArgsForIds(ids));
}

public int remove(long... ids) {
    if (ids == null || ids.length == 0) {
        // called with nothing to remove!
        throw new IllegalArgumentException(
                "input param 'ids' can't be null");
    }
    return mResolver.delete(mBaseUri, getWhereClauseForIds(ids),
            getWhereArgsForIds(ids));
}

public Cursor query(Query query) {
    Cursor underlyingCursor = query.runQuery(mResolver, UNDERLYING_COLUMNS,
            mBaseUri);
    if (underlyingCursor == null) {
        return null;
    }
    return new CursorTranslator(underlyingCursor, mBaseUri);
}

public ParcelFileDescriptor openDownloadedFile(long id)
        throws FileNotFoundException {
    return mResolver.openFileDescriptor(getDownloadUri(id), "r");
}

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));
}

/**
 * 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 getColumnIndex(String columnName) {
        return Arrays.asList(COLUMNS).indexOf(columnName);
    }

    @Override
    public int getColumnIndexOrThrow(String columnName)
            throws IllegalArgumentException {
        int index = getColumnIndex(columnName);
        if (index == -1) {
            throw new IllegalArgumentException("No such column: "
                    + columnName);
        }
        return index;
    }

    @Override
    public String getColumnName(int columnIndex) {
        int numColumns = COLUMNS.length;
        if (columnIndex < 0 || columnIndex >= numColumns) {
            throw new IllegalArgumentException("Invalid column index "
                    + columnIndex + ", " + numColumns + " columns exist");
        }
        return COLUMNS[columnIndex];
    }

    @Override
    public String[] getColumnNames() {
        String[] returnColumns = new String[COLUMNS.length];
        System.arraycopy(COLUMNS, 0, returnColumns, 0, COLUMNS.length);
        return returnColumns;
    }

    @Override
    public int getColumnCount() {
        return COLUMNS.length;
    }

    @Override
    public byte[] getBlob(int columnIndex) {
        throw new UnsupportedOperationException();
    }

    @Override
    public double getDouble(int columnIndex) {
        return getLong(columnIndex);
    }

    private boolean isLongColumn(String column) {
        return LONG_COLUMNS.contains(column);
    }

    @Override
    public float getFloat(int columnIndex) {
        return (float) getDouble(columnIndex);
    }

    @Override
    public int getInt(int columnIndex) {
        return (int) getLong(columnIndex);
    }

    @Override
    public long getLong(int columnIndex) {
        return translateLong(getColumnName(columnIndex));
    }

    @Override
    public short getShort(int columnIndex) {
        return (short) getLong(columnIndex);
    }

    @Override
    public String getString(int columnIndex) {
        return translateString(getColumnName(columnIndex));
    }

    private String translateString(String column) {
        if (isLongColumn(column)) {
            return Long.toString(translateLong(column));
        }
        if (column.equals(COLUMN_TITLE)) {
            return getUnderlyingString(Downloads.COLUMN_TITLE);
        }
        if (column.equals(COLUMN_DESCRIPTION)) {
            return getUnderlyingString(Downloads.COLUMN_DESCRIPTION);
        }
        if (column.equals(COLUMN_URI)) {
            return getUnderlyingString(Downloads.COLUMN_URI);
        }
        if (column.equals(COLUMN_MEDIA_TYPE)) {
            return getUnderlyingString(Downloads.COLUMN_MIME_TYPE);
        }
        if (column.equals(COLUMN_MEDIAPROVIDER_URI)) {
            return getUnderlyingString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
        }

        assert column.equals(COLUMN_LOCAL_URI);
        return getLocalUri();
    }

    private String getLocalUri() {
        long destinationType = getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
        if (destinationType == Downloads.Impl.DESTINATION_FILE_URI) {
            // return client-provided file URI for external download
            return getUnderlyingString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
        }

        if (destinationType == Downloads.Impl.DESTINATION_EXTERNAL) {
            // return stored destination for legacy external download
            String localPath = getUnderlyingString(Downloads.Impl._DATA);
            if (localPath == null) {
                return null;
            }
            return Uri.fromFile(new File(localPath)).toString();
        }

        // return content URI for cache download
        long downloadId = getUnderlyingLong(Downloads.Impl._ID);
        return ContentUris.withAppendedId(mBaseUri, downloadId).toString();
    }

    private long translateLong(String column) {
        if (!isLongColumn(column)) {
            // mimic behavior of underlying cursor -- most likely, throw
            // NumberFormatException
            return Long.valueOf(translateString(column));
        }

        if (column.equals(COLUMN_ID)) {
            return getUnderlyingLong(Downloads.Impl._ID);
        }
        if (column.equals(COLUMN_TOTAL_SIZE_BYTES)) {
            return getUnderlyingLong(Downloads.COLUMN_TOTAL_BYTES);
        }
        if (column.equals(COLUMN_STATUS)) {
            return translateStatus((int) getUnderlyingLong(Downloads.COLUMN_STATUS));
        }
        if (column.equals(COLUMN_REASON)) {
            return getReason((int) getUnderlyingLong(Downloads.COLUMN_STATUS));
        }
        if (column.equals(COLUMN_BYTES_DOWNLOADED_SO_FAR)) {
            return getUnderlyingLong(Downloads.COLUMN_CURRENT_BYTES);
        }
        assert column.equals(COLUMN_LAST_MODIFIED_TIMESTAMP);
        return getUnderlyingLong(Downloads.COLUMN_LAST_MODIFICATION);
    }

    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.STATUS_FILE_ERROR:
            return ERROR_FILE_ERROR;

        case Downloads.STATUS_UNHANDLED_HTTP_CODE:
        case Downloads.STATUS_UNHANDLED_REDIRECT:
            return ERROR_UNHANDLED_HTTP_CODE;

        case Downloads.STATUS_HTTP_DATA_ERROR:
            return ERROR_HTTP_DATA_ERROR;

        case Downloads.STATUS_TOO_MANY_REDIRECTS:
            return ERROR_TOO_MANY_REDIRECTS;

        case Downloads.STATUS_INSUFFICIENT_SPACE_ERROR:
            return ERROR_INSUFFICIENT_SPACE;

        case Downloads.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;

        default:
            return ERROR_UNKNOWN;
        }
    }

    private long getUnderlyingLong(String column) {
        return super.getLong(super.getColumnIndex(column));
    }

    private String getUnderlyingString(String column) {
        return super.getString(super.getColumnIndex(column));
    }

    private int translateStatus(int status) {
        switch (status) {
        case Downloads.STATUS_PENDING:
            return STATUS_PENDING;

        case Downloads.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.STATUS_SUCCESS:
            return STATUS_SUCCESSFUL;

        default:
            assert Downloads.isStatusError(status);
            return STATUS_FAILED;
        }
    }
}
public final class Downloads {
/**
 *    @hide     
 */
private Downloads() {}
/**
 * The permission to access the download manager
 *    @hide      .
 */
public static final String PERMISSION_ACCESS = "android.permission.ACCESS_DOWNLOAD_MANAGER";

/**
 * The permission to access the download manager's advanced functions
 * @hide
 */
public static final String PERMISSION_ACCESS_ADVANCED =
        "android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED";

/**
 * The permission to directly access the download manager's cache directory
 * @hide
 */
public static final String PERMISSION_CACHE = "android.permission.ACCESS_CACHE_FILESYSTEM";

/**
 * The permission to send broadcasts on download completion
 * @hide
 */
public static final String PERMISSION_SEND_INTENTS =
        "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS";

/**
 * The content:// URI for the data table in the provider
 * @hide
 */
public static final Uri CONTENT_URI =
    Uri.parse("content://downloads/my_downloads");

/**
 * 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.
 * @hide
 */
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.
 * @hide
 */
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>
 * @hide
 */
public static final String COLUMN_URI = "uri";


public static final String COLUMN_APP_DATA = "entity";


public static final String COLUMN_NO_INTEGRITY = "no_integrity";


public static final String COLUMN_FILE_NAME_HINT = "hint";


public static final String _DATA = "_data";


public static final String COLUMN_MIME_TYPE = "mimetype";


public static final String COLUMN_DESTINATION = "destination";


public static final String COLUMN_VISIBILITY = "visibility";


public static final String COLUMN_CONTROL = "control";


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>
 * @hide
 */
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>
 * @hide
 */
public static final String COLUMN_NOTIFICATION_PACKAGE = "notificationpackage";


public static final String COLUMN_NOTIFICATION_CLASS = "notificationclass";


public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras";


public static final String COLUMN_COOKIE_DATA = "cookiedata";


public static final String COLUMN_USER_AGENT = "useragent";


public static final String COLUMN_REFERER = "referer";


public static final String COLUMN_TOTAL_BYTES = "total_bytes";


public static final String COLUMN_CURRENT_BYTES = "current_bytes";


public static final String COLUMN_OTHER_UID = "otheruid";


public static final String COLUMN_TITLE = "title";


public static final String COLUMN_DESCRIPTION = "description";


public static final String COLUMN_DELETED = "deleted";


public static final int DESTINATION_EXTERNAL = 0;


public static final int DESTINATION_CACHE_PARTITION = 1;


public static final int DESTINATION_CACHE_PARTITION_PURGEABLE = 2;


public static final int DESTINATION_CACHE_PARTITION_NOROAMING = 3;


public static final int CONTROL_RUN = 0;


public static final int CONTROL_PAUSED = 1;



/**
 * Returns whether the status is informational (i.e. 1xx).
 * @hide
 */
public static boolean isStatusInformational(int status) {
    return (status >= 100 && status < 200);
}


public static boolean isStatusSuccess(int status) {
    return (status >= 200 && status < 300);
}


public static boolean isStatusError(int status) {
    return (status >= 400 && status < 600);
}


public static boolean isStatusClientError(int status) {
    return (status >= 400 && status < 500);
}

public static boolean isStatusServerError(int status) {
    return (status >= 500 && status < 600);
}


public static boolean isStatusCompleted(int status) {
    return (status >= 200 && status < 300) || (status >= 400 && status < 600);
}


public static final int STATUS_PENDING = 190;


public static final int STATUS_RUNNING = 192;


public static final int STATUS_SUCCESS = 200;


public static final int STATUS_BAD_REQUEST = 400;


public static final int STATUS_NOT_ACCEPTABLE = 406;


public static final int STATUS_LENGTH_REQUIRED = 411;


public static final int STATUS_PRECONDITION_FAILED = 412;


public static final int STATUS_CANCELED = 490;


public static final int STATUS_UNKNOWN_ERROR = 491;


public static final int STATUS_FILE_ERROR = 492;


public static final int STATUS_UNHANDLED_REDIRECT = 493;


public static final int STATUS_UNHANDLED_HTTP_CODE = 494;


public static final int STATUS_HTTP_DATA_ERROR = 495;


public static final int STATUS_HTTP_EXCEPTION = 496;


public static final int STATUS_TOO_MANY_REDIRECTS = 497;


public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;


public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;


public static final int VISIBILITY_VISIBLE = 0;


public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;


public static final int VISIBILITY_HIDDEN = 2;


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");

    public static final Uri ALL_DOWNLOADS_CONTENT_URI =
            Uri.parse("content://downloads/all_downloads");


    public static final String ACTION_DOWNLOAD_COMPLETED =
            "android.intent.action.DOWNLOAD_COMPLETED";

    public static final String ACTION_NOTIFICATION_CLICKED =
            "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";


    public static final String COLUMN_URI = "uri";


    public static final String COLUMN_APP_DATA = "entity";

    public static final String COLUMN_NO_INTEGRITY = "no_integrity";


    public static final String COLUMN_FILE_NAME_HINT = "hint";


    public static final String _DATA = "_data";


    public static final String COLUMN_MIME_TYPE = "mimetype";


    public static final String COLUMN_DESTINATION = "destination";


    public static final String COLUMN_VISIBILITY = "visibility";

    public static final String COLUMN_CONTROL = "control";

    public static final String COLUMN_STATUS = "status";


    public static final String COLUMN_LAST_MODIFICATION = "lastmod";


    public static final String COLUMN_NOTIFICATION_PACKAGE = "notificationpackage";


    public static final String COLUMN_NOTIFICATION_CLASS = "notificationclass";


    public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras";


    public static final String COLUMN_COOKIE_DATA = "cookiedata";


    public static final String COLUMN_USER_AGENT = "useragent";


    public static final String COLUMN_REFERER = "referer";


    public static final String COLUMN_TOTAL_BYTES = "total_bytes";


    public static final String COLUMN_CURRENT_BYTES = "current_bytes";


    public static final String COLUMN_OTHER_UID = "otheruid";


    public static final String COLUMN_TITLE = "title";


    public static final String COLUMN_DESCRIPTION = "description";


    public static final String COLUMN_IS_PUBLIC_API = "is_public_api";


    public static final String COLUMN_ALLOW_ROAMING = "allow_roaming";


    public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types";


    public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui";


    public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT =
        "bypass_recommended_size_limit";


    public static final String COLUMN_DELETED = "deleted";


    public static final String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";

    /*
     * Lists the destinations that an application can specify for a download.
     */


    public static final int DESTINATION_EXTERNAL = 0;


    public static final int DESTINATION_CACHE_PARTITION = 1;


    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 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;



    /**
     * 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);
    }

    /**
     * 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;


    public static final int STATUS_SUCCESS = 200;


    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;


    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;


    public static final int STATUS_UNKNOWN_ERROR = 491;


    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 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 = 498;

    /**
     * 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 = 499;

    /**
     * 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_";
    }
  }
}