2016-07-24 2 views
2

Я следую за a tutorial to download files using the Retrofit library.Обработка нескольких загрузок с помощью уведомлений с использованием библиотеки дооснащения

Пользовательский интерфейс моего приложения имеет несколько различных кнопок, которые загружают разные файлы с использованием вышеуказанного метода. Проблема в том, что когда кто-то нажимает другую кнопку после нажатия первой, она ставится в очередь и начинается после первого завершения. Я хочу, чтобы он начинался сразу.

Вот код 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 классов. Do Service классы позволяют одновременную загрузку? Я пробовал что-то вроде этого:

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) { 

    } 
} 

Но это не сработало. Какие-нибудь подсказки, что я должен делать? Я готов предоставить более подробную информацию, если потребуется.

Редактировать 1: DownloadService работает с функцией «startDownload», которая выполняется различными кнопками. Как вы можете видеть во втором коде, класс Extends Service. Существует один поток, который обрабатывает все эти нажатия кнопок. Если вы посмотрите в комментариях, мне предлагается использовать Сервис и разные потоки для всех этих кликов. Теперь, как я могу сделать так много потоков программно. Есть около 40 кнопок, которые используют DownloadService.

+0

Кажется, служба может иметь только один экземпляр, работающий в то время. Итак, если вы выполняете загрузку файла, он продолжает работать при попытке запустить новый. Я бы попытался больше узнать о одновременной загрузке. Я думаю, что вы можете запускать различные задачи async каждый раз, когда ваша служба получает запрос на загрузку файла, или, может быть, более простой поток, который просто загружает файлы. Служба будет получать запросы и управлять потоками. Но прежде, чем это сделать, я бы поискал советы по лучшим практикам. – Lxu

+0

Надеюсь, что кто-то выйдет с решением. –

+1

Я думаю, что следующие темы имеют ответ, который вы ищете: http://stackoverflow.com/questions/19875838/download-multiple-files-with-a-progress-bar-in-listview-android http: // stackoverflow .com/questions/25659657/how-to-download-multiple-files-concurrently-using-intentservice-in-android – Lxu

ответ

1

Благодаря @Lxu, у меня есть работа. Таким образом, IntentService предназначен для выполнения одной задачи одновременно и не может выполнять несколько задач одновременно. Вместо этого мы должны использовать Service. Он позволяет одновременно выполнять несколько задач. Мы можем создать несколько потоков внутри Service, которые будут выполняться одновременно. Моя проблема была решена путем помещения всего кода onCreate() в onStartCommand(). Когда вызывается услуга в первый раз, вызывается onCreate(), и после этого он не вызывается больше, независимо от того, сколько раз вызывается служба. При каждом вызове службы выполняется onStartCommand(), который создает новый поток каждый раз. Вот и все.

Вот полный код:

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) { 

    } 
} 
+0

как мы можем остановить службу после того, как загрузка будет завершена – TheGreat004

+0

как для одного я могу ее остановить – TheGreat004

Смежные вопросы