使用翻新库处理带有通知的多个下载 [英] Handling Multiple Downloads With Notifications Using Retrofit Library

查看:93
本文介绍了使用翻新库处理带有通知的多个下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注使用Retrofit下载文件的教程库

我的应用程序的UI有几个不同的按钮,可使用上述方法下载不同的文件。问题是当某人在按下第一个按钮后又按下另一个按钮时,该按钮排队并在第一个按钮完成后才开始。我希望它同时开始。

My app's UI has several different buttons which download different files using the above method. The problem is when someone presses another button after pressing the first, it's queued and starts after the first finishes. I want it to start right away simultaneously.

这是 DownloadService 的代码:

public class DownloadService extends IntentService {

    public DownloadService() {
        super("Download Service");
    }

    private int totalFileSize;
    private NotificationCompat.Builder notificationBuilder;
    private NotificationManager notificationManager;

    @Override
    protected void onHandleIntent(Intent intent) {
        MyApp x = (MyApp)getApplicationContext();
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
                .setContentTitle("Downloading")
                .setContentText("Please wait...")
                .setAutoCancel(true);
        notificationManager.notify(x.ID, notificationBuilder.build());
        Log.i("Paras", "onHandleIntent: " + x.filename + x.url);
        initDownload(x.filename,x.url,x.ID);

    }

    private void initDownload(String filename, String url, int id) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://dl.dropboxusercontent.com/")
                .build();

        RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);

        Call<ResponseBody> request = retrofitInterface.downloadFile(url);
        try {

            downloadFile(request.execute().body(),filename,id);

        } catch (IOException e) {

            e.printStackTrace();
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();

        }
    }

    private void downloadFile(ResponseBody body, String filename,int id) throws IOException {

        int count;
        byte data[] = new byte[1024 * 4];
        long fileSize = body.contentLength();
        InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
        File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
        OutputStream output = new FileOutputStream(outputFile);
        long total = 0;
        long startTime = System.currentTimeMillis();
        int timeCount = 1;

        while ((count = bis.read(data)) != -1) {
            total += count;
            totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
            double current = Math.round(total / (Math.pow(1, 2))) / 1000;

            int progress = (int) ((total * 100) / fileSize);

            long currentTime = System.currentTimeMillis() - startTime;

            Download download = new Download();
            download.setTotalFileSize(totalFileSize);

            if (currentTime > 1000 * timeCount) {
                download.setCurrentFileSize((int) current);
                download.setProgress(progress);
                sendNotification(download,id);
                timeCount++;
            }

            output.write(data, 0, count);
        }

        onDownloadComplete(filename,id);
        output.flush();
        output.close();
        bis.close();

    }

    private void sendNotification(Download download, int id) {

        sendIntent(download);
        notificationBuilder.setProgress(100, download.getProgress(), false);
        notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
        notificationManager.notify(id, notificationBuilder.build());
    }

    private void sendIntent(Download download) {

        Intent intent = new Intent(subject.MESSAGE_PROGRESS);
        intent.putExtra("download", download);
        LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
    }

    private void onDownloadComplete(String filename,int id) {
        try {

            Download download = new Download();
            download.setProgress(100);
            sendIntent(download);

            notificationManager.cancel(id);
            notificationBuilder.setProgress(0, 0, false);
            notificationBuilder.setContentText("Tap to open");
            notificationManager.notify(id, notificationBuilder.build());

            String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;

            File file = new File(path1);
            Uri uri_path = Uri.fromFile(file);
            String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
                    (MimeTypeMap.getFileExtensionFromUrl(path1));

            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
            intent.setType(mimeType);
            intent.setDataAndType(uri_path, mimeType);
            PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
            String string = filename;
            notificationBuilder
                    .setContentIntent(pIntent)
                    .setAutoCancel(true)
                    .setContentTitle(string + " Downloaded");
            Log.i("Paras", "onDownloadComplete: " + string);
            notificationManager.notify(id, notificationBuilder.build());
        } catch (Exception ex) {

        }
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {

    }
}

然后我读到了 IntentService Service 类。 Service 类是否允许同时下载?我尝试过这样的事情:

Then I read about IntentService and Service classes. Do Service classes allow simultaneous downloads? I tried something like this:

public class DownloadService extends Service {

    public DownloadService() {
        super();
    }

    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            MyApp x = (MyApp)getApplicationContext();
            notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            notificationBuilder = new NotificationCompat.Builder(getBaseContext())
                    .setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
                    .setContentTitle("Downloading")
                    .setContentText("Please wait...")
                    .setAutoCancel(true);
            notificationManager.notify(x.ID, notificationBuilder.build());
            Log.i("Paras", "onHandleIntent: " + x.filename + x.url);
            initDownload(x.filename,x.url,x.ID);
        }
    }

    @Override
    public void onCreate() {
        // Start up the thread running the service.  Note that we create a
        // separate thread because the service normally runs in the process's
        // main thread, which we don't want to block.  We also make it
        // background priority so CPU-intensive work will not disrupt our UI.
        HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        // Get the HandlerThread's Looper and use it for our Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        MyApp x = (MyApp)getApplicationContext();
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj= intent.putExtra("ID",x.ID);
        mServiceHandler.sendMessage(msg);

        // If we get killed, after returning from here, restart
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private int totalFileSize;
    private NotificationCompat.Builder notificationBuilder;
    private NotificationManager notificationManager;

    private void initDownload(String filename, String url, int id) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://dl.dropboxusercontent.com/")
                .build();

        RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);

        Call<ResponseBody> request = retrofitInterface.downloadFile(url);
        try {

            downloadFile(request.execute().body(),filename,id);

        } catch (IOException e) {

            e.printStackTrace();
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();

        }
    }

    private void downloadFile(ResponseBody body, String filename,int id) throws IOException {

        int count;
        byte data[] = new byte[1024 * 4];
        long fileSize = body.contentLength();
        InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
        File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
        OutputStream output = new FileOutputStream(outputFile);
        long total = 0;
        long startTime = System.currentTimeMillis();
        int timeCount = 1;

        while ((count = bis.read(data)) != -1) {
            total += count;
            totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
            double current = Math.round(total / (Math.pow(1, 2))) / 1000;

            int progress = (int) ((total * 100) / fileSize);

            long currentTime = System.currentTimeMillis() - startTime;

            Download download = new Download();
            download.setTotalFileSize(totalFileSize);

            if (currentTime > 1000 * timeCount) {
                download.setCurrentFileSize((int) current);
                download.setProgress(progress);
                sendNotification(download,id);
                timeCount++;
            }

            output.write(data, 0, count);
        }

        onDownloadComplete(filename,id);
        output.flush();
        output.close();
        bis.close();

    }

    private void sendNotification(Download download, int id) {

        sendIntent(download);
        notificationBuilder.setProgress(100, download.getProgress(), false);
        notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
        notificationManager.notify(id, notificationBuilder.build());
    }

    private void sendIntent(Download download) {

        Intent intent = new Intent(subject.MESSAGE_PROGRESS);
        intent.putExtra("download", download);
        LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
    }

    private void onDownloadComplete(String filename,int id) {
        try {

            Download download = new Download();
            download.setProgress(100);
            sendIntent(download);

            notificationManager.cancel(id);
            notificationBuilder.setProgress(0, 0, false);
            notificationBuilder.setContentText("Tap to open");
            notificationManager.notify(id, notificationBuilder.build());

            String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;

            File file = new File(path1);
            Uri uri_path = Uri.fromFile(file);
            String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
                    (MimeTypeMap.getFileExtensionFromUrl(path1));

            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
            intent.setType(mimeType);
            intent.setDataAndType(uri_path, mimeType);
            PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
            String string = filename;
            notificationBuilder
                    .setContentIntent(pIntent)
                    .setAutoCancel(true)
                    .setContentTitle(string + " Downloaded");
            Log.i("Paras", "onDownloadComplete: " + string);
            notificationManager.notify(id, notificationBuilder.build());
        } catch (Exception ex) {

        }
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {

    }
}

但这没用。有什么线索我该怎么办?如果需要的话,我准备提供更多详细信息。

But it didn't work. Any clues what I should do? I'm ready to give more details if required.

编辑1: DownloadService在 startDownload函数上运行,该函数由各种按钮执行。如您在第二代码中所见,类扩展服务。有一个线程可以处理所有这些按钮单击。如果您有任何评论,建议我对所有这些点击使用服务和其他线程。现在如何以编程方式创建这么多线程。几乎有40个按钮可以使用DownloadService。

Edit 1: DownloadService runs on a function "startDownload" which is executed by various buttons. As you can see in 2nd code, class Extends Service. There is one thread which handles all those button clicks. If you look in comments, it's suggested that I should use Service and different threads for all those clicks. Now how can I make so many threads programmatically. There are almost 40 buttons which make use of DownloadService.

推荐答案

感谢@Lxu,我已经开始使用它了。因此, IntentService 只能一次执行一项任务,而不能同时执行多项任务。我们应该改为使用 Service 。它允许同时执行多个任务。我们可以在 Service 内部创建多个线程,这些线程将同时执行。通过将 onCreate()的所有代码放入 onStartCommand(),解决了我的问题。首次调用服务时,会调用 onCreate(),此后无论调用多少次,都不会再调用它。在每个服务调用中,执行 onStartCommand()每次都会创建一个新线程。而已。

Thanks to @Lxu, I have got it working. So IntentServiceis meant to do one task at a time and can't do multiple tasks simultaneously. We should use Serviceinstead. It allows multiple tasks to be performed simultaneously. We can create multiple threads inside the Service which will be executed simultaneously. My problem got solved by putting all the code of onCreate() to onStartCommand(). When a service is called for the first time, onCreate() is called and after that, it's not called anymore no matter how many times service is called. On every service call, onStartCommand() is executed which creates new thread every time. That's it.

这是完整的代码:

public class DownloadService extends Service {

    public DownloadService() {
        super();
    }
    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;

    int id1;
    int id2;
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            MyApp x = (MyApp)getApplicationContext();
            notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            notificationBuilder = new NotificationCompat.Builder(getApplicationContext())
                    .setSmallIcon(R.drawable.ic_file_download_deep_orange_a400_18dp)
                    .setContentTitle("Downloading")
                    .setContentText("Please wait...")
                    .setAutoCancel(true);
            notificationManager.notify(x.ID, notificationBuilder.build());
            Log.i("Paras", "onHandleIntent: " + x.filename + x.url + "  " + x.ID);
            initDownload(x.filename,x.url,x.ID);
        }
    }
    @Override
    public void onCreate() {
        // Get the HandlerThread's Looper and use it for our Handler
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
        MyApp x = (MyApp)getApplicationContext();
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);


        // If we get killed, after returning from here, restart
        return START_STICKY;
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    private int totalFileSize;
    private NotificationCompat.Builder notificationBuilder;
    private NotificationManager notificationManager;

    private void initDownload(String filename, String url, int id) {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://dl.dropboxusercontent.com/")
                .build();

        RequestInterface.RetrofitInterface retrofitInterface = retrofit.create(RequestInterface.RetrofitInterface.class);

        Call<ResponseBody> request = retrofitInterface.downloadFile(url);
        try {

            downloadFile(request.execute().body(),filename,id);

        } catch (IOException e) {

            e.printStackTrace();
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();

        }
    }

    private void downloadFile(ResponseBody body, String filename,int id) throws IOException {

        int count;
        byte data[] = new byte[1024 * 4];
        long fileSize = body.contentLength();
        InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
        File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename);
        OutputStream output = new FileOutputStream(outputFile);
        long total = 0;
        long startTime = System.currentTimeMillis();
        int timeCount = 1;
        while ((count = bis.read(data)) != -1) {

            total += count;
            totalFileSize = (int) (fileSize / (Math.pow(1, 2))) / 1000;
            double current = Math.round(total / (Math.pow(1, 2))) / 1000;

            int progress = (int) ((total * 100) / fileSize);

            long currentTime = System.currentTimeMillis() - startTime;

            Download download = new Download();
            download.setTotalFileSize(totalFileSize);

            if (currentTime > 1000 * timeCount) {

                download.setCurrentFileSize((int) current);
                download.setProgress(progress);
                sendNotification(download,id);
                timeCount++;
            }

            output.write(data, 0, count);
        }
        onDownloadComplete(filename,id);
        output.flush();
        output.close();
        bis.close();

    }

    private void sendNotification(Download download, int id) {

        sendIntent(download,id);
        notificationBuilder.setProgress(100, download.getProgress(), false)
                            .setContentTitle("Downloading");
        notificationBuilder.setContentText("Downloading file " + download.getCurrentFileSize() + "/" + totalFileSize + " KB");
        notificationManager.notify(id, notificationBuilder.build());
    }

    private void sendIntent(Download download, int id) {

        Intent intent = new Intent(subject.MESSAGE_PROGRESS);
        intent.putExtra("download", download);
        LocalBroadcastManager.getInstance(DownloadService.this).sendBroadcast(intent);
    }

    private void onDownloadComplete(String filename,int id) {
        try {

            Download download = new Download();
            download.setProgress(100);
            sendIntent(download,id);

            notificationManager.cancel(id);
            notificationBuilder.setProgress(0, 0, false);
            notificationBuilder.setContentText("Tap to open");
            notificationManager.notify(id, notificationBuilder.build());

            String path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + filename;

            File file = new File(path1);
            Uri uri_path = Uri.fromFile(file);
            String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension
                    (MimeTypeMap.getFileExtensionFromUrl(path1));

            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
            intent.setType(mimeType);
            intent.setDataAndType(uri_path, mimeType);
            PendingIntent pIntent = PendingIntent.getActivity(this,(int) System.currentTimeMillis(), intent, 0);
            String string = filename;
            notificationBuilder
                    .setContentIntent(pIntent)
                    .setAutoCancel(true)
                    .setContentTitle(string + " Downloaded");
            Log.i("Paras", "onDownloadComplete: " + string);
            notificationManager.notify(id, notificationBuilder.build());
        }catch (Exception ex){

        }
    }
    @Override
    public void onTaskRemoved(Intent rootIntent) {

    }
}

这篇关于使用翻新库处理带有通知的多个下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆