简体   繁体   中英

Download Manager Unable to Resume Download in case of Internet Disconnection and System Reboot

I have created a simple application which is supposed to download large zip files. After some R&D I came to the conclusion that I have to use Download Manager to achieve this. I want the download to resume automatically if the device is restarted or in case of unstable internet connectivity . Right now, the code is able to download large files as expected, but in case of internet connectivity fluctuations or system restart, it stops downloading.

The activity:

public class MainActivity extends ActionBarActivity {

    String Download_path = "http://wickedbrains.com/map/mumbai.zip";
     String Download_ID = "DOWNLOAD_ID";

     SharedPreferences preferenceManager;
     DownloadManager downloadManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        preferenceManager = PreferenceManager.getDefaultSharedPreferences(this);
           downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);

           Button btnDownload = (Button)findViewById(R.id.download);
           btnDownload.setOnClickListener(new Button.OnClickListener(){

       @Override
       public void onClick(View arg0) {

        // Locate storage location
            String filepath = "";

            File folder = new File(
                    Environment.getExternalStorageDirectory() + "/osmdroid");
            boolean success = true;
            if (!folder.exists()) {
                success = folder.mkdir();
            }
            if (success) {
                // Do something on success
                filepath = Environment.getExternalStorageDirectory()
                        .getPath() + "/osmdroid";

                // Deleting if zip file exists
                File folder2 = Environment.getExternalStorageDirectory();
                String fileName = folder2.getPath() + "/osmdroid/mumbai.zip";

                File myFile = new File(fileName);
                if(myFile.exists())
                    myFile.delete();

            }


    //Starting download manager to download file
        Uri Download_Uri = Uri.parse(Download_path);
        DownloadManager.Request request = new DownloadManager.Request(Download_Uri);

        long download_id =  downloadManager.enqueue(request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
                .setAllowedOverRoaming(false)
                .setTitle("Test")
                .setDescription("Map Download")
                .setDestinationInExternalPublicDir("/osmdroid","mumbai.zip"));

       // long download_id = downloadManager.enqueue(request);

        //Save the download id
        Editor PrefEdit = preferenceManager.edit();
        PrefEdit.putLong(Download_ID, download_id);
        PrefEdit.commit();
       }});
       }

     @Override
     protected void onResume() {
      // TODO Auto-generated method stub
      super.onResume();

      IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
      registerReceiver(downloadReceiver, intentFilter);
     }

     @Override
     protected void onPause() {
      // TODO Auto-generated method stub
      super.onPause();

      unregisterReceiver(downloadReceiver);
     }

     private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {

      @Override
      public void onReceive(Context arg0, Intent arg1) {
       // TODO Auto-generated method stub
       DownloadManager.Query query = new DownloadManager.Query();
       query.setFilterById(preferenceManager.getLong(Download_ID, 0));
       Cursor cursor = downloadManager.query(query);

       if(cursor.moveToFirst()){
        int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
        int status = cursor.getInt(columnIndex);
        int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
        int reason = cursor.getInt(columnReason);

        if(status == DownloadManager.STATUS_SUCCESSFUL){
         //Retrieve the saved download id
         long downloadID = preferenceManager.getLong(Download_ID, 0);

         ParcelFileDescriptor file;
         try {
          file = downloadManager.openDownloadedFile(downloadID);
          Toast.makeText(MainActivity.this,
            "File Downloaded: " + file.toString(),
            Toast.LENGTH_LONG).show();
         } catch (FileNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
          Toast.makeText(MainActivity.this,
            e.toString(),
            Toast.LENGTH_LONG).show();
         }

        }else if(status == DownloadManager.STATUS_FAILED){
         Toast.makeText(MainActivity.this,
           "FAILED!\n" + "reason of " + reason,
           Toast.LENGTH_LONG).show();
        }else if(status == DownloadManager.STATUS_PAUSED){
         Toast.makeText(MainActivity.this,
           "PAUSED!\n" + "reason of " + reason,
           Toast.LENGTH_LONG).show();
        }else if(status == DownloadManager.STATUS_PENDING){
         Toast.makeText(MainActivity.this,
           "PENDING!",
           Toast.LENGTH_LONG).show();
        }else if(status == DownloadManager.STATUS_RUNNING){
         Toast.makeText(MainActivity.this,
           "RUNNING!",
           Toast.LENGTH_LONG).show();
        }
       }
      }

     };

    }

Where am I going wrong? What should I do to enable the resume capability of the download?

Quoting from docs,

The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots.

I guess Download Manager, by default takes cares of retries.

If you are having issues you can use DownloadManager.Query class and query for COLUMN_STATUS and COLUMN_REASON to get the download status

Edit:

Starting a download

dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request( YOUR_DOWNLOAD_URL );
long enqueue = dm.enqueue(request);

enqueue is more like a download reqeust id. You can use that enqueue to fetch the download progress/status

Querying the download Status

Query query = new Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {

    int downloadStatus = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));

    if (DownloadManager.STATUS_SUCCESSFUL == downloadStatus) {
        // download succeded
    } else if (DownloadManager.STATUS_FAILED == downloadStatus){
        String failedReason = c.getString(c.getColumnIndex(DownloadManager.COLUMN_REASON));
        // handle failures
    }
}

Haven't tested the code myself. But it should work.

Try to get the reason for the failed download. eg does it work on network switch wifi->data

(If your error reason is 1008- there seems to be a reported bug here

https://code.google.com/p/android/issues/detail?id=18462 ,

further:

http://papaya-backend.net/2013/04/12/why-http-etag-header-may-cause-your-downloading-apps-on-android-failed/ )

I confirm that this problem still exists in 2020, when testing in an emulator and having WiFi enabled, this error consistently appears (even with Android 10).

Switching off WiFi in the emulator seems to solve the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM