1

Background

I wish to use DownloadManager in order to download multiple files to the device, and also be able to show the progress on the activity, with more details than shown on the notification.

I know this was asked before (post here), but they use polling with a background thread, plus I'm not sure what kind of data I can get from it.

The question

Is it possible to show the progress details without polling? maybe through a listener/broadcastReceiver ?

Community
  • 1
  • 1
android developer
  • 114,585
  • 152
  • 739
  • 1,270

1 Answers1

0

It is not possible. DownloadManager has only 3 broadcasts:

ACTION_DOWNLOAD_COMPLETE(for completion) ACTION_NOTIFICATION_CLICKED(click its notification) ACTION_VIEW_DOWNLOADS(to view the file download)

So, I think polling is necessary to monitor the progress.

My Download Service:

package com.codebrew.govideodownloader;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class DownloadService extends IntentService {
String urlD, name, sole;
Context conte;
static int q = -1, counter = -1;
int progress = 0, nin;
double tmp = 0;
int oldP = 0;
File file;
public static final String NOTIFICATION = "com.codebrewlabs.vidbox.ShowDownloadsActivity";
SharedPreferences pre;
NotificationManager notificationManager;
NotificationCompat.Builder mBuilder;

public DownloadService(String name) {
    super("Downloading");
}

public DownloadService() {
    super("Downloading");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    q = q + 1;
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onCreate() {
    super.onCreate();
    conte = this;
}

@Override
protected void onHandleIntent(Intent intent) {
    try {
        notificationManager = (NotificationManager) conte
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(conte)
                .setSmallIcon(R.drawable.vidbox_icon)
                .setContentTitle("My notification")
                .setContentText("Hello World!");
        pre = getSharedPreferences("VidBoxPref", 0);
        urlD = intent.getExtras().getString("url");
        name = intent.getExtras().getString("name");
        nin = intent.getExtras().getInt("nin");
        progress = 0;
        sole = name;
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        double size = 0;
        final int TIMEOUT_CONNECTION = 30000;// 30sec
        final int TIMEOUT_SOCKET = 30000;// 30sec
        String imageURL = urlD;
        URL url = new URL(imageURL);
        long startTime = System.currentTimeMillis();
        Log.e("Note: ", "image download beginning: " + imageURL);
        // Open a connection to that URL.
        URLConnection ucon = url.openConnection();

        // this timeout affects how long it takes for the app to realize
        // there's a connection problem
        ucon.setReadTimeout(TIMEOUT_CONNECTION);
        ucon.setConnectTimeout(TIMEOUT_SOCKET);

        // Define InputStreams to read from the URLConnection.
        // uses 3KB download buffer
        InputStream is = ucon.getInputStream();
        size = ucon.getContentLength();
        BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
        File wallpaperDirectory = new File(
                Environment.getExternalStorageDirectory()
                        + "/Video/GoVideoDownloader");
        wallpaperDirectory.mkdirs();
        // sole = sole.replace("?", "_");
        // sole = sole.replace("|", "_");
        // sole = sole.replace("/", "_");
        // sole = sole.replace(":", "_");
        // sole = sole.replace("$", "_");
        file = new File(wallpaperDirectory + File.separator + sole);
        if (file.exists()) {
            file.delete();
        }
        file.createNewFile();
        pre.edit().putBoolean("inDownload", true).commit();
        publishP();
        FileOutputStream outStream = new FileOutputStream(file);
        byte[] buff = new byte[5 * 1024];

        // Read bytes (and store them) until there is nothing more to
        // read(-1)
        int len;
        tmp = 0;
        while ((len = inStream.read(buff)) != -1) {
            if (pre.getBoolean("cont", false)) {
                pre.edit().putBoolean("cont", false).commit();
                pre.edit().putBoolean("inDownload", false).commit();
                q--;
                pre.edit().putInt("progress", progress).commit();
                sendNotification(7, nin, sole);
                Intent in2 = new Intent(NOTIFICATION);
                in2.putExtra("progress", progress);
                in2.putExtra("running", 0);
                in2.putExtra("name", sole);
                in2.putExtra("resume", "0");
                sendBroadcast(in2);
                progress = 0;
                outStream.close();
                stopSelf();
                return;
            }
            tmp = tmp + len;
            progress = (int) (((double) tmp / size) * 100);
            pre.edit().putInt("progress", progress).commit();
            if (progress < 0)
                progress = -1 * progress;
            outStream.write(buff, 0, len);
            if (progress != oldP)
                publishP();
            oldP = progress;
        }
        tmp = size;
        progress = 100;
        q = q + 1;
        publishP();
        // clean up

        outStream.flush();
        outStream.close();
        inStream.close();
        Log.e("Note: ",
                "Download completed in "
                        + ((System.currentTimeMillis() - startTime) / 1000)
                        + " secs.");
    } catch (Exception e) {
        if (file != null) {
            if (file.exists()) {
                file.delete();
            }
        }
        pre.edit().putBoolean("inDownload", false).commit();
        int innn;
        if (e.toString()
                .equals("java.io.IOException: open failed: EACCES (Permission denied)")) {
            innn = 5;
        } else {
            innn = 1;
        }
        if (!e.toString().equals(
                "java.io.IOException: close failed: EIO (I/O error)")) {
            sendNotification(innn, nin, sole);
        }
        Intent in2 = new Intent(NOTIFICATION);
        in2.putExtra("progress", progress);
        in2.putExtra("running", 0);
        in2.putExtra("name", sole);
        q--;
        in2.putExtra("resume", "0");

        sendBroadcast(in2);
        progress = 0;
        Log.e("Error: ", "Error is:" + e.toString());
    }
}

protected void publishP() {
    try {
        pre.edit().putInt("progress", progress).commit();
        sendNotification(0, nin, sole);
        Intent in2 = new Intent(NOTIFICATION);
        if (progress == 100) {
            q--;
            pre.edit().putBoolean("inDownload", false).commit();
        }
        in2.putExtra("progress", progress);
        in2.putExtra("resume", "0");
        in2.putExtra("running", 1);
        in2.putExtra("name", sole);
        in2.putExtra("queue", q);
        pre.edit().putInt("progress", progress).commit();
        pre.edit().putInt("running", 1).commit();
        pre.edit().putString("currName", sole).commit();
        pre.edit().putInt("nowQueue", q).commit();
        sendBroadcast(in2);
    } catch (Exception e) {
        Log.e("Shit", e.toString());
    }
}

@Override
public boolean stopService(Intent name) {
    return super.stopService(name);
}

public void sendNotification(int tmout, int nin, String name) {
    if (tmout == 0) {

        // notificationManager.notify(nin, mBuilder.build());
        if (progress >= 100) {
            // notificationManager.cancel(nin);
            mBuilder.setSmallIcon(R.drawable.vidbox_icon)
                    .setContentTitle("Completed").setContentText(name)
                    .setAutoCancel(true).setOngoing(false);
            Uri ttt = Uri.parse(Environment.getExternalStorageDirectory()
                    + File.separator + "Video/GoVideoDownloader/" + name);
            Uri uri = RingtoneManager
                    .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            mBuilder.setSound(uri);
            pre.edit().putInt("retry", 1).commit();
            Intent inten = new Intent(Intent.ACTION_VIEW, ttt);
            String arr[] = name.split("\\.");
            inten.setDataAndType(ttt, "video/" + arr[arr.length - 1]);
            PendingIntent i = PendingIntent.getActivity(conte, 0, inten, 0);
            mBuilder.setContentIntent(i);
            notificationManager.notify(nin, mBuilder.build());
        } else {
            mBuilder.setContentTitle("Downloading: " + name)
                    .setContentText(progress + " %")
                    .setSmallIcon(R.drawable.vidbox_icon)
                    .setAutoCancel(false).setOngoing(true);
            mBuilder.setProgress(100, progress, false);
            notificationManager.notify(nin, mBuilder.build());
        }
    } else {
        if (tmout == 1) {
            mBuilder.setSmallIcon(R.drawable.vidbox_icon)
                    .setContentTitle("Failed").setContentText(name)
                    .setContentText(progress + " %").setAutoCancel(true)
                    .setProgress(100, progress, false).setOngoing(false);
            Uri uri = RingtoneManager
                    .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            mBuilder.setSound(uri);
            Intent intnt = new Intent(NOTIFICATION);
            intnt.putExtra("resume", "1");
            intnt.putExtra("url", urlD);
            intnt.putExtra("name", name);
            intnt.putExtra("nin", nin);
            // PendingIntent i = PendingIntent
            // .getBroadcast(conte, 0, intnt, 0);
            // mBuilder.setContentIntent(i);
        } else if (tmout == 7) {
            mBuilder.setSmallIcon(R.drawable.vidbox_icon)
                    .setContentTitle("Cancelled").setContentText(name)
                    .setAutoCancel(true).setProgress(100, progress, false)
                    .setOngoing(false);
            Intent intnt = new Intent(NOTIFICATION);
            intnt.putExtra("resume", "1");
            intnt.putExtra("url", urlD);
            intnt.putExtra("name", name);
            intnt.putExtra("nin", nin);
            // PendingIntent i = PendingIntent
            // .getBroadcast(conte, 0, intnt, 0);
            // mBuilder.setContentIntent(i);
            Uri uri = RingtoneManager
                    .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            mBuilder.setSound(uri);
        } else {
            mBuilder.setSmallIcon(R.drawable.vidbox_icon)
                    .setContentTitle("Interrupted").setContentText(name)
                    .setContentText("No storage found").setAutoCancel(true)
                    .setOngoing(false);
            Uri uri = RingtoneManager
                    .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            mBuilder.setSound(uri);
        }

        notificationManager.notify(nin, mBuilder.build());
    }
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
    try {
        notificationManager.cancel(nin);
        pre.edit().putBoolean("inDownload", false).commit();
    } catch (Exception e) {
    }
}
}

I am downloading the bytes of file using a loop, and sending broadcasts and notifications for each byte downloaded(or whenever progress increments). Hope it helps :3

berserk
  • 2,690
  • 3
  • 32
  • 63