user4516999
user4516999

Reputation:

Check if Download Manager downloaded the file

How can I check if file has been downloaded and run its installation? I have a code:

public void downloadUpdate(String url){

    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
    request.setDescription("Downloading...");
    request.setTitle("App Update");
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

    String name = URLUtil.guessFileName(url, null, MimeTypeMap.getFileExtensionFromUrl(url));

    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, name);

    DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    manager.enqueue(request);
}

Upvotes: 3

Views: 10443

Answers (3)

yazan sayed
yazan sayed

Reputation: 1139

If you want the system to notify you when a download is complete you can use the BroadcastReceiver solution.
However if you want to get the status of a download manually, you can use this code, you don't need to add a receiver to the manifest file.
N.B. the interface is added for testing purposes, you can discard it if you wish.


interface Downloader {
    fun downloadFile(url: String,folderName:String,fileName:String): Long
}

class AndroidDownloader(
    private val context: Context
): Downloader {

    private val downloadManager = context.getSystemService(DownloadManager::class.java)

    override fun downloadFile(url: String,folderName:String,fileName:String): Long {
        val request = DownloadManager.Request(url.toUri())
            .setMimeType("image/jpeg")
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)
            .setTitle(fileName)
            .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "$folderName/$fileName")
        return downloadManager.enqueue(request)
    }


    fun is_download_complete(downloadId: Long): Boolean {
        val query = DownloadManager.Query()
        query.setFilterById(downloadId)
        val cursor = downloadManager?.query(query)
        if (cursor == null) {
            return false
        }
        if (!cursor.moveToFirst()) {
            cursor.close()
            return false
        }
        val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
        val status = cursor.getInt(columnIndex)
        cursor.close()
        return status == DownloadManager.STATUS_SUCCESSFUL || status == DownloadManager.STATUS_FAILED
    }
}

Upvotes: 0

huskygrad
huskygrad

Reputation: 1407

This is relatively an easy method. It worked for me: You need to add the <receiver> tag in the manifest file as follows:

 <application>
 <receiver
            android:name= "com.example.checkDownloadComplete" <!-- add desired full name here --> 
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
 </receiver>
 </application>

This will register a Broadcast Receiver for an event where your download is completed. This will call the onReceive() method in your class as soon as download completes. Remember that you need to extend the BroadcastReceiver class, but not implement it. I declared a boolean variable as a toggle to check completion of download. Hence, your Java class will be something like:

public static class checkDownloadComplete extends BroadcastReceiver{

     public static boolean isDownloadComplete= false;

     @Override
     public void onReceive(Context context, Intent intent) {
         isDownloadComplete = true;
         Log.i("Download completed?", String.valueOf(isDownloadComplete));
     }

}

To wait until or check whether your download has completed from any other class, use the following simple code in the desired appropriate place:

while(!checkDownloadComplete.isDownloadComplete){

    // add necessary code to be executed before completion of download
}
//code after completion of download

But remember that if you need to check it multiple times in your project, then you'll need to reset the value of isDownloadComplete beforehand.

Upvotes: 0

Joey Chong
Joey Chong

Reputation: 1510

To check whether the download manager downloaded the file, you must implements your BroatcastReceiver.

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0));
        DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        Cursor cursor = manager.query(query);
        if (cursor.moveToFirst()) {
            if (cursor.getCount() > 0) {
                int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                if (status == DownloadManager.STATUS_SUCCESSFUL) {
                    String file = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
                    // So something here on success
                } else {
                    int message = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
                    // So something here on failed.
                }
            }
        }
    }
}

However, I am not sure whether you can install the APK programmatically. For security reason, I don't think you can. For application update, I think you should use google versioning control. When you re-deploy your app using different version number, the users should able to update automatically (unless user turn off at google play). Hope that this will help.

Update

You do not need to call the method that I mention. You just need to declare your broadcast receiver at your manifest xml file and DownloadManager will call at when download complete. The xml look something like below:

    <receiver
        android:name=".BroadcastReceiver"
        android:enabled="true"
        android:exported="true" >
        <intent-filter>
            <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
        </intent-filter>
    </receiver>

Upvotes: 11

Related Questions