2013-02-10 10 views
13

Ho utilizzato la classe Download Manager all'interno della mia attività per eseguire download; funziona bene e il mio prossimo compito è mostrare la stessa percentuale di progresso all'interno della mia attività. Non sono sicuro di come farlo.Mostra avanzamento download manager all'interno dell'attività

Il mio codice finora

public class DownloadSampleBook extends Activity{ 

private long enqueue; 
private DownloadManager dm; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_sample_download); 

    BroadcastReceiver receiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String action = intent.getAction(); 
      if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) { 
       long downloadId = intent.getLongExtra(
         DownloadManager.EXTRA_DOWNLOAD_ID, 0); 
       Query query = new Query(); 
       query.setFilterById(enqueue); 
       Cursor c = dm.query(query); 
       if (c.moveToFirst()) { 
        int columnIndex = c 
          .getColumnIndex(DownloadManager.COLUMN_STATUS); 
        if (DownloadManager.STATUS_SUCCESSFUL == c 
          .getInt(columnIndex)) { 

         view.setImageURI(Uri.parse(uriString)); 
        } 
       } 
      } 
     } 
    }; 

    registerReceiver(receiver, new IntentFilter(
      DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 
} 

public void onClick(View view) { 
    dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); 
    Request request = new Request(
      Uri.parse("http://abc.com/a.png")); 
    enqueue = dm.enqueue(request); 

} 

public void showDownload(View view) { 
    Intent i = new Intent(); 
    i.setAction(DownloadManager.ACTION_VIEW_DOWNLOADS); 
    startActivity(i); 
} 
} 

Esiste un metodo che dia la percentuale di avanzamento del download?

+0

Vuoi sapere anche tu. Nessuna soluzione chiara a questo –

risposta

17

È possibile eseguire una query sul numero di byte scaricati finora e sul numero totale di byte che devono essere scaricati, utilizzando il metodo , più o meno allo stesso modo in cui si è richiesto lo stato nel codice di esempio. Una volta ottenuti questi valori, è abbastanza facile calcolare il progresso come percentuale.

Non sembra essere un modo per ricevere una notifica quando vengono ricevuti nuovi dati, quindi spetterà a voi il polling del download manager a intervalli regolari per determinare lo stato corrente di qualsiasi download che voglio monitorare.

Query query = new Query(); 
query.setfilterById(downloadId); 

Cursor c = dm.query(query); 
if (c.moveToFirst()) { 
    int sizeIndex = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES); 
    int downloadedIndex = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); 
    long size = c.getInt(sizeIndex); 
    long downloaded = c.getInt(downloadedIndex); 
    double progress = 0.0; 
    if (size != -1) progress = downloaded*100.0/size; 
    // At this point you have the progress as a percentage. 
} 

Si noti che la dimensione totale sarà inizialmente -1 e verrà completata solo dopo l'avvio del download. Quindi nel codice di esempio sopra ho controllato per -1 e impostare il progresso su 0 se la dimensione non è ancora impostata.

Tuttavia, in alcuni casi è possibile che la dimensione totale non venga mai restituita (ad esempio, in un trasferimento chunked HTTP, non ci sarà un'intestazione Content-Length da cui è possibile determinare la dimensione). Se hai bisogno di supportare questo tipo di server, dovresti probabilmente fornire qualche tipo di indicazione all'utente che il download sta procedendo e non solo una barra di avanzamento che è bloccata a zero.

+0

Non si dovrebbe verificare la dimensione per i valori zero? Qualcosa come scaricato * 100.0/(size == 0? 1: size) – Fabiano

18

Se siete alla ricerca di un modo dignitoso per determinare quando per interrogare il DownloadManager per gli aggiornamenti sullo stato di avanzamento, considerare la registrazione di un ContentObserver per l'uri content://downloads/my_downloads

Esempio:

DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); 
manager.enqueue(myRequest); 

Uri myDownloads = Uri.parse("content://downloads/my_downloads"); 
getContentResolver().registerContentObserver(myDownloads, true, new DownloadObserver()); 

... 

public static class DownloadObserver extends ContentObserver { 
    @Override 
    public void onChange(boolean selfChange, Uri uri) { 
     Log.d("DownloadObserver", "Download " + uri + " updated"); 
    } 

Questo produce il seguente output come ogni pezzo del download di lunga durata è ricevuto

D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated 
D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated 
D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated 
D/DownloadObserver(15584): Download content://downloads/my_downloads/437 updated 

dove '437' è l'ID del tuo download.

Si noti che questo segue l'URI di contenuto definito nella classe android.provider.Downloads che sembra essere nascosto nel framework e potrebbe non funzionare in modo coerente su tutti i dispositivi. (https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/provider/Downloads.java#89)

0

Avevo l'obbligo di rintracciare il download di più file. Dopo un sacco di pensare e sperimentare, mi si avvicinò con il seguente codice:

private void startDownloadThread(final List<DownloadFile> list) { 

     // Initializing the broadcast receiver ... 
     mBroadCastReceiver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       mFinishedFilesFromNotif.add(intent.getExtras() 
         .getLong(DownloadManager.EXTRA_DOWNLOAD_ID)); 
      } 
     }; 

     IntentFilter intentFilter = new IntentFilter(
       "android.intent.action.DOWNLOAD_COMPLETE"); 
     DownloadProgressUIFragment.this.getActivity().registerReceiver(mBroadCastReceiver, 
       intentFilter); 

     // initializing the download manager instance .... 
     mDownloadManager = (DownloadManager) getActivity() 
       .getSystemService(Context.DOWNLOAD_SERVICE); 

     // adding files to the download manager list ... 
     for(DownloadFile f: list) { 
      mDownloadIds.add(FileUtils.addFileForDownloadInBkg(getApplicationContext(), 
        f.getUrl(), 
        f.getPath())); 
     } 

     // starting the thread to track the progress of the download .. 
     mProgressThread = new Thread(new Runnable() { 
      @Override 
      public void run() { 

       // Preparing the query for the download manager ... 
       DownloadManager.Query q = new DownloadManager.Query(); 
       long[] ids = new long[mDownloadIds.size()]; 
       final List<Long> idsArrList= new ArrayList<>(); 
       int i = 0; 
       for (Long id: mDownloadIds) { 
        ids[i++] = id; 
        idsArrList.add(id); 
       } 
       q.setFilterById(ids); 

       // getting the total size of the data ... 
       Cursor c; 

       while(true) { 

        // check if the downloads are already completed ... 
        // Here I have created a set of download ids from download manager to keep 
        // track of all the files that are dowloaded, which I populate by creating 
        // 
        if(mFinishedFilesFromNotif.containsAll(idsArrList)) { 
         isDownloadSuccess = true; 

         // TODO - Take appropriate action. Download is finished successfully 
         return; 
        } 

        // start iterating and noting progress .. 
        c = mDownloadManager.query(q); 
        if(c != null) { 
         int filesDownloaded = 0; 
         float fileFracs = 0f; // this stores the fraction of all the files in 
         // download 
         final int columnTotalSize = c.getColumnIndex 
           (DownloadManager.COLUMN_TOTAL_SIZE_BYTES); 
         final int columnStatus = c.getColumnIndex(DownloadManager.COLUMN_STATUS); 
         //final int columnId = c.getColumnIndex(DownloadManager.COLUMN_ID); 
         final int columnDwnldSoFar = 
           c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR); 

         while (c.moveToNext()) { 
          // checking the progress .. 
          if(c.getInt(columnStatus) == DownloadManager.STATUS_SUCCESSFUL) { 
           filesDownloaded++; 
          } 
          // If the file is partially downloaded, take its fraction .. 
          else if(c.getInt(columnTotalSize) > 0) { 
           fileFracs += ((c.getInt(columnDwnldSoFar) * 1.0f)/
             c.getInt(columnTotalSize)); 
          } else if(c.getInt(columnStatus) == DownloadManager.STATUS_FAILED) { 
           // TODO - Take appropriate action. Error in downloading one of the 
           // files. 
           return; 
          } 
         } 

         c.close(); 

         // calculate the progress to show ... 
         float progress = (filesDownloaded + fileFracs)/ids.length; 

         // setting the progress text and bar... 
         final int percentage = Math.round(progress * 100.0f); 
         final String txt = "Loading ... " + percentage + "%"; 

         // Show the progress appropriately ... 
        } 
       } 
      } 
     }); 

     mProgressThread.start(); 
    } 

E la funzione per accodare a file sono:

public static long addFileForDownloadInBkg(Context context, String url, String savePath) { 
     Uri uri = Uri.parse(url); 
     DownloadManager.Request request = new DownloadManager.Request(uri); 
     request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); 
     request.setDestinationUri(Uri.fromFile(new File(savePath))); 

     final DownloadManager m = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); 
     return m.enqueue(request); 
    } 

In sostanza, ricevo una notifica individualmente per ciascuna delle file il cui download è stato completato e quindi li aggiungo a un set che è fondamentalmente il set che mi aiuta a decidere se tutti i download sono stati completati o meno. Traccio i progressi in base al numero di file e alla frazione di ciascuno completa. Spero che aiuti.

Problemi correlati