2016-07-24 2 views
2

私はa tutorial to download files using the Retrofit libraryに従っています。Retrofitライブラリを使用した通知による複数ダウンロードの処理

私のアプリのUIには、上記の方法で異なるファイルをダウンロードするいくつかのボタンがあります。問題は、誰かが最初のボタンを押した後に別のボタンを押したときにキューに入れられ、最初の終了後に開始するときです。私はそれをすぐに同時に開始したい。ここで

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

    } 
} 

その後、私はおよそIntentServiceServiceクラスをお読みください。 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」関数で実行されます。 2番目のコードでわかるように、classはサービスを拡張します。これらのボタンのクリックをすべて処理するスレッドが1つあります。コメントを見ると、これらのすべてのクリックに対してServiceと異なるスレッドを使用する必要があることが示唆されています。では、どうやって多くのスレッドをプログラムで作ることができますか? DownloadServiceを利用するボタンは40個近くあります。

+0

は、サービスが一度に実行されているつのインスタンスを持つことができるようです。あなたがサービスしているのは、新しいファイルを開こうとすると実行中のファイルをダウンロードすることです。私は同時ダウンロードについてさらに検索しようとします。私はあなたのサービスがダウンロードファイル呼び出しを受け取るたびに、あるいは単にファイルをダウンロードするより簡単なスレッドを受け取るたびに、異なる非同期タスクを開始できると思います。サービスは要求を受け取り、スレッドを制御します。しかし、私はそれを行う前に、このケースのベストプラクティスのヒントを探します。 – 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-with-intentservice-in-android – Lxu

答えて

1

@ Lxuのおかげで、私はそれを働かせました。したがって、IntentServiceは一度に1つのタスクを実行するためのもので、複数のタスクを同時に実行することはできません。代わりに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

関連する問題