-1

I am trying to download file from url and save it to general downloads folder. setDestinationInExternalPublicDir() doesn't work and doesn't throw any exception. But setDestinationInExternalFilesDir() works fine. Any idea what the reason can be ?

My code is like this:

webView.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent,
                                String contentDisposition, String mimeType,
                                long contentLength) {

        if (url.startsWith("data:")) {
            save(url);
            return;
        }


        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setMimeType(mimeType);
        String cookies = CookieManager.getInstance().getCookie(url);
        request.addRequestHeader("cookie", cookies);
        request.addRequestHeader("User-Agent", userAgent);
        request.setDescription(getResources().getString(R.string.downloadingMsg));
        String filename = URLUtil.guessFileName(url, contentDisposition, mimeType);
        request.setTitle(filename);
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//DOESN'T WORK
            request.setDestinationInExternalPublicDir("Downloads", filename); 
//WORKS
            //request.setDestinationInExternalFilesDir(getApplicationContext(), "Downloads", filename); 
        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        dm.enqueue(request);
        Toast.makeText(getApplicationContext(), R.string.downloadingMsg, Toast.LENGTH_LONG).show();
    }
});

And manifest file:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Elnoor
  • 3,401
  • 4
  • 24
  • 39

2 Answers2

2

So, i finally could get the setDestinationInExternalPublicDir() function work. Thanks to CommonsWare. By following Commonsware's comment and answer here I learnt that on android versions 6+, even though permissions declared in manifest file, they should still be requested on runtime as well. And guess what, i was working with android 7... That is way, i was getting permission denied error.

So i added these lines on my onCreate() function which will prompt users for the permission on runtime as well (which solved my problem finally):

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        int PERMISSION_REQUEST_CODE = 1;
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            } else {
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        PERMISSION_REQUEST_CODE);
            }
        }
    }
Elnoor
  • 3,401
  • 4
  • 24
  • 39
0

My solution for download image from url.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.CalendarContract;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.UUID;

public class DownloadImage extends AsyncTask<String, Void, Bitmap> implements MediaScannerConnection.MediaScannerConnectionClient {

    private Context context;
    private File mFile;
    private MediaScannerConnection mMs;


    public DownloadImage(Context context) {
        this.context = context;
    }

    private Bitmap downloadImageBitmap(String sUrl) {
        Bitmap bitmap = null;
        try {
            InputStream inputStream = new URL(sUrl).openStream();   // Download Image from URL
            bitmap = BitmapFactory.decodeStream(inputStream);       // Decode Bitmap
            inputStream.close();
        } catch (Exception e) {
            Log.d(TAG, "Exception 1, Something went wrong!");
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        return downloadImageBitmap(params[0]);
    }

    protected void onPostExecute(Bitmap result) {
        String fileName = UUID.randomUUID().toString();
        getFilePath(fileName + ".jpg", result, context);
    }


    public void getFilePath(String name, Bitmap bitmap2, Context context) {
        Bitmap bitmap = bitmap2;
        String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();//Downloads folder path
        File myDir = new File(root);
        myDir.mkdirs();
        String fname = name.replaceAll("-", "");
        File file = new File(myDir, fname);
        if (file.exists()) {
            file.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            Toast.makeText(context, "Error occurred", Toast.LENGTH_SHORT).show();
            return;
        }

        Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show();

        mFile = file;
        mMs = new MediaScannerConnection(context, this);//finding image in gallery after download 
        mMs.connect();

    }

    @Override
    public void onMediaScannerConnected() {
        mMs.scanFile(mFile.getAbsolutePath(), null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        mMs.disconnect();
    }
}

Running this class in Activity:

DownloadImage downloadImage = new DownloadImage(this);
downloadImage.execute("url");

UPD1: I think you can use for file downloading this code.