alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (Downloads.java)

This example Android source code file (Downloads.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

android, content, contentresolver, context, cursor, download_id_invalid, downloadbase, downloads_projection, io, network, os, provider, query_where_app_data_clause, query_where_clause, status_downloaded_update, status_downloading_update, status_invalid, statusinfo, string, uri

The Downloads.java Android example source code

/*
 * 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 android.net;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.provider.BaseColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
import java.io.InputStream;

/**
 * The Download Manager
 *
 * @hide
 */
public final class Downloads {


    /**
     * Download status codes
     */

    /**
     * This download hasn't started yet
     */
    public static final int STATUS_PENDING = 190;

    /**
     * This download has started
     */
    public static final int STATUS_RUNNING = 192;

    /**
     * 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 download can't be performed because the content type cannot be
     * handled.
     */
    public static final int STATUS_NOT_ACCEPTABLE = 406;

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

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

    /**
     * Download destinations
     */

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

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

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


    /**
     * An invalid download id
     */
    public static final long DOWNLOAD_ID_INVALID = -1;


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

    /**
     * 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>Owner can Init

*/ public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras"; /** * Status class for a download */ public static final class StatusInfo { public boolean completed = false; /** The filename of the active download. */ public String filename = null; /** An opaque id for the download */ public long id = DOWNLOAD_ID_INVALID; /** An opaque status code for the download */ public int statusCode = -1; /** Approximate number of bytes downloaded so far, for debugging purposes. */ public long bytesSoFar = -1; /** * Returns whether the download is completed * @return a boolean whether the download is complete. */ public boolean isComplete() { return android.provider.Downloads.Impl.isStatusCompleted(statusCode); } /** * Returns whether the download is successful * @return a boolean whether the download is successful. */ public boolean isSuccessful() { return android.provider.Downloads.Impl.isStatusCompleted(statusCode); } } /** * Class to access initiate and query download by server uri */ public static final class ByUri extends DownloadBase { /** @hide */ private ByUri() {} /** * Query where clause by app data. * @hide */ private static final String QUERY_WHERE_APP_DATA_CLAUSE = android.provider.Downloads.Impl.COLUMN_APP_DATA + "=?"; /** * Gets a Cursor pointing to the download(s) of the current system update. * @hide */ private static final Cursor getCurrentOtaDownloads(Context context, String url) { return context.getContentResolver().query( android.provider.Downloads.Impl.CONTENT_URI, DOWNLOADS_PROJECTION, QUERY_WHERE_APP_DATA_CLAUSE, new String[] {url}, null); } /** * Returns a StatusInfo with the result of trying to download the * given URL. Returns null if no attempts have been made. */ public static final StatusInfo getStatus( Context context, String url, long redownload_threshold) { StatusInfo result = null; boolean hasFailedDownload = false; long failedDownloadModificationTime = 0; Cursor c = getCurrentOtaDownloads(context, url); try { while (c != null && c.moveToNext()) { if (result == null) { result = new StatusInfo(); } int status = getStatusOfDownload(c, redownload_threshold); if (status == STATUS_DOWNLOADING_UPDATE || status == STATUS_DOWNLOADED_UPDATE) { result.completed = (status == STATUS_DOWNLOADED_UPDATE); result.filename = c.getString(DOWNLOADS_COLUMN_FILENAME); result.id = c.getLong(DOWNLOADS_COLUMN_ID); result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS); result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES); return result; } long modTime = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION); if (hasFailedDownload && modTime < failedDownloadModificationTime) { // older than the one already in result; skip it. continue; } hasFailedDownload = true; failedDownloadModificationTime = modTime; result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS); result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES); } } finally { if (c != null) { c.close(); } } return result; } /** * Query where clause for general querying. */ private static final String QUERY_WHERE_CLAUSE = android.provider.Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + "=? AND " + android.provider.Downloads.Impl.COLUMN_NOTIFICATION_CLASS + "=?"; /** * Delete all the downloads for a package/class pair. */ public static final void removeAllDownloadsByPackage( Context context, String notification_package, String notification_class) { context.getContentResolver().delete( android.provider.Downloads.Impl.CONTENT_URI, QUERY_WHERE_CLAUSE, new String[] { notification_package, notification_class }); } /** * The column for the id in the Cursor returned by * getProgressCursor() */ public static final int getProgressColumnId() { return 0; } /** * The column for the current byte count in the Cursor returned by * getProgressCursor() */ public static final int getProgressColumnCurrentBytes() { return 1; } /** * The column for the total byte count in the Cursor returned by * getProgressCursor() */ public static final int getProgressColumnTotalBytes() { return 2; } /** @hide */ private static final String[] PROJECTION = { BaseColumns._ID, android.provider.Downloads.Impl.COLUMN_CURRENT_BYTES, android.provider.Downloads.Impl.COLUMN_TOTAL_BYTES }; /** * Returns a Cursor representing the progress of the download identified by the ID. */ public static final Cursor getProgressCursor(Context context, long id) { Uri downloadUri = Uri.withAppendedPath(android.provider.Downloads.Impl.CONTENT_URI, String.valueOf(id)); return context.getContentResolver().query(downloadUri, PROJECTION, null, null, null); } } /** * Class to access downloads by opaque download id */ public static final class ById extends DownloadBase { /** @hide */ private ById() {} /** * Get the mime tupe of the download specified by the download id */ public static String getMimeTypeForId(Context context, long downloadId) { ContentResolver cr = context.getContentResolver(); String mimeType = null; Cursor downloadCursor = null; try { Uri downloadUri = getDownloadUri(downloadId); downloadCursor = cr.query( downloadUri, new String[]{android.provider.Downloads.Impl.COLUMN_MIME_TYPE}, null, null, null); if (downloadCursor.moveToNext()) { mimeType = downloadCursor.getString(0); } } finally { if (downloadCursor != null) downloadCursor.close(); } return mimeType; } /** * Delete a download by Id */ public static void deleteDownload(Context context, long downloadId) { ContentResolver cr = context.getContentResolver(); String mimeType = null; Uri downloadUri = getDownloadUri(downloadId); cr.delete(downloadUri, null, null); } /** * Open a filedescriptor to a particular download */ public static ParcelFileDescriptor openDownload( Context context, long downloadId, String mode) throws FileNotFoundException { ContentResolver cr = context.getContentResolver(); String mimeType = null; Uri downloadUri = getDownloadUri(downloadId); return cr.openFileDescriptor(downloadUri, mode); } /** * Open a stream to a particular download */ public static InputStream openDownloadStream(Context context, long downloadId) throws FileNotFoundException, IOException { ContentResolver cr = context.getContentResolver(); String mimeType = null; Uri downloadUri = getDownloadUri(downloadId); return cr.openInputStream(downloadUri); } private static Uri getDownloadUri(long downloadId) { return Uri.parse(android.provider.Downloads.Impl.CONTENT_URI + "/" + downloadId); } /** * Returns a StatusInfo with the result of trying to download the * given URL. Returns null if no attempts have been made. */ public static final StatusInfo getStatus( Context context, long downloadId) { StatusInfo result = null; boolean hasFailedDownload = false; long failedDownloadModificationTime = 0; Uri downloadUri = getDownloadUri(downloadId); ContentResolver cr = context.getContentResolver(); Cursor c = cr.query( downloadUri, DOWNLOADS_PROJECTION, null /* selection */, null /* selection args */, null /* sort order */); try { if (!c.moveToNext()) { return result; } if (result == null) { result = new StatusInfo(); } int status = getStatusOfDownload(c,0); if (status == STATUS_DOWNLOADING_UPDATE || status == STATUS_DOWNLOADED_UPDATE) { result.completed = (status == STATUS_DOWNLOADED_UPDATE); result.filename = c.getString(DOWNLOADS_COLUMN_FILENAME); result.id = c.getLong(DOWNLOADS_COLUMN_ID); result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS); result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES); return result; } long modTime = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION); result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS); result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES); } finally { if (c != null) { c.close(); } } return result; } } /** * Base class with common functionality for the various download classes */ public static class DownloadBase { /** @hide */ DownloadBase() {} /** * Initiate a download where the download will be tracked by its URI. */ public static long startDownloadByUri( Context context, String url, String cookieData, boolean showDownload, int downloadDestination, boolean allowRoaming, boolean skipIntegrityCheck, String title, String notification_package, String notification_class, String notification_extras) { ContentResolver cr = context.getContentResolver(); // Tell download manager to start downloading update. ContentValues values = new ContentValues(); values.put(android.provider.Downloads.Impl.COLUMN_URI, url); values.put(android.provider.Downloads.Impl.COLUMN_COOKIE_DATA, cookieData); values.put(android.provider.Downloads.Impl.COLUMN_VISIBILITY, showDownload ? android.provider.Downloads.Impl.VISIBILITY_VISIBLE : android.provider.Downloads.Impl.VISIBILITY_HIDDEN); if (title != null) { values.put(android.provider.Downloads.Impl.COLUMN_TITLE, title); } values.put(android.provider.Downloads.Impl.COLUMN_APP_DATA, url); // NOTE: destination should be seperated from whether the download // can happen when roaming int destination = android.provider.Downloads.Impl.DESTINATION_EXTERNAL; switch (downloadDestination) { case DOWNLOAD_DESTINATION_EXTERNAL: destination = android.provider.Downloads.Impl.DESTINATION_EXTERNAL; break; case DOWNLOAD_DESTINATION_CACHE: if (allowRoaming) { destination = android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION; } else { destination = android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING; } break; case DOWNLOAD_DESTINATION_CACHE_PURGEABLE: destination = android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE; break; } values.put(android.provider.Downloads.Impl.COLUMN_DESTINATION, destination); values.put(android.provider.Downloads.Impl.COLUMN_NO_INTEGRITY, skipIntegrityCheck); // Don't check ETag if (notification_package != null && notification_class != null) { values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, notification_package); values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_CLASS, notification_class); if (notification_extras != null) { values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, notification_extras); } } Uri downloadUri = cr.insert(android.provider.Downloads.Impl.CONTENT_URI, values); long downloadId = DOWNLOAD_ID_INVALID; if (downloadUri != null) { downloadId = Long.parseLong(downloadUri.getLastPathSegment()); } return downloadId; } } /** @hide */ private static final int STATUS_INVALID = 0; /** @hide */ private static final int STATUS_DOWNLOADING_UPDATE = 3; /** @hide */ private static final int STATUS_DOWNLOADED_UPDATE = 4; /** * Column projection for the query to the download manager. This must match * with the constants DOWNLOADS_COLUMN_*. * @hide */ private static final String[] DOWNLOADS_PROJECTION = { BaseColumns._ID, android.provider.Downloads.Impl.COLUMN_APP_DATA, android.provider.Downloads.Impl.COLUMN_STATUS, android.provider.Downloads.Impl._DATA, android.provider.Downloads.Impl.COLUMN_LAST_MODIFICATION, android.provider.Downloads.Impl.COLUMN_CURRENT_BYTES, }; /** * The column index for the ID. * @hide */ private static final int DOWNLOADS_COLUMN_ID = 0; /** * The column index for the URI. * @hide */ private static final int DOWNLOADS_COLUMN_URI = 1; /** * The column index for the status code. * @hide */ private static final int DOWNLOADS_COLUMN_STATUS = 2; /** * The column index for the filename. * @hide */ private static final int DOWNLOADS_COLUMN_FILENAME = 3; /** * The column index for the last modification time. * @hide */ private static final int DOWNLOADS_COLUMN_LAST_MODIFICATION = 4; /** * The column index for the number of bytes downloaded so far. * @hide */ private static final int DOWNLOADS_COLUMN_CURRENT_BYTES = 5; /** * Gets the status of a download. * * @param c A Cursor pointing to a download. The URL column is assumed to be valid. * @return The status of the download. * @hide */ private static final int getStatusOfDownload( Cursor c, long redownload_threshold) { int status = c.getInt(DOWNLOADS_COLUMN_STATUS); long realtime = SystemClock.elapsedRealtime(); // TODO(dougz): special handling of 503, 404? (eg, special // explanatory messages to user) if (!android.provider.Downloads.Impl.isStatusCompleted(status)) { // Check if it's stuck long modified = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION); long now = System.currentTimeMillis(); if (now < modified || now - modified > redownload_threshold) { return STATUS_INVALID; } return STATUS_DOWNLOADING_UPDATE; } if (android.provider.Downloads.Impl.isStatusError(status)) { return STATUS_INVALID; } String filename = c.getString(DOWNLOADS_COLUMN_FILENAME); if (filename == null) { return STATUS_INVALID; } return STATUS_DOWNLOADED_UPDATE; } /** * @hide */ private Downloads() {} }

Other Android examples (source code examples)

Here is a short list of links related to this Android Downloads.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.