How to download WebView files to the SDCard if available

1

The App is a simple browser that works like WebView. This code causes the files to be downloaded to a custom folder and works perfectly.

mWebView.setDownloadListener(new DownloadListener() {

            @SuppressLint("InlinedApi") public void onDownloadStart(String url, String userAgent,
                                                                    String contentDisposition, String mimetype,
                                                                    long contentLength) {
                DownloadManager.Request request = new DownloadManager.Request(
                        Uri.parse(url));

                request.allowScanningByMediaScanner();
                final String filename = URLUtil.guessFileName(url, contentDisposition, mimetype);
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
                //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
                request.setDestinationInExternalPublicDir("/Nome da Pasta", filename);
                DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                dm.enqueue(request);
                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); //This is important!
                intent.addCategory(Intent.CATEGORY_OPENABLE); //CATEGORY.OPENABLE
                intent.setType("*/*");//any application,any extension
                Toast.makeText(getApplicationContext(), "Baixando", //To notify the Client that the file is being downloaded
                        Toast.LENGTH_LONG).show();

            }
        });
  

The problem is that they are going to the memory of the phone. If the phone has an SDCard inserted, how do I get the files to be downloaded directly to the SDCard?

    
asked by anonymous 29.07.2016 / 21:17

1 answer

1

You are using request.setDestinationInExternalPublicDir() which, as the name implies, would be external memory. The problem may be that newer devices may have more than one type of memory external . In addition to the SDCard, they may have some internal (fixed) considered as external.

The fact that minSdk is 9 somewhat restricts how to secure the path for the SDCard, so I do not guarantee that the next method works in all cases. (*)

public Uri getSDCardPathIfAvailable(){

    //Se o "primary external path" é um SDCard retorna-o
    if(Environment.isExternalStorageRemovable()) {
        return Uri.fromFile(getExternalFilesDir(null));
    }
    //Ler todos os "external paths"(não garanto se Android < 19)
    File[] externalDirs =  ContextCompat.getExternalFilesDirs(this, null);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        for(File externalDir : externalDirs){
            if(Environment.isExternalStorageRemovable(externalDir)){
                return Uri.fromFile(externalDir);
            }
        }
        return null;
    }

    //Não podendo fazer melhor, talvez, com sorte, o segundo seja o SDCard
    else if(externalDirs.length > 1 && externalDirs[1] != null){
        return Uri.fromFile(externalDirs[1]);
    }
    return null;
}

Place this method in your class and replace the line

request.setDestinationInExternalPublicDir("/Nome da Pasta", filename);

by

Uri uri = getSDCardPathIfAvailable();
if(uri != null){
    request.setDestinationUri(uri.buildUpon().appendPath(filename).build());
}else{
    //Não foi encontrado um SDCard(mas pode existir)
}
Samsung Galaxy Tab2 (4.1.2), which has more than one "external memory" (fixed + SDCard), ContextCompat.getExternalFilesDirs() returned only to fixed. In Samsung Galaxy Tab3 (4.4.2) has returned both. If the methods ContextCompat.getExternalFilesDirs() and Environment.isExternalStorageRemovable(File externalDir) do what is said in the documentation the method will work in version 21 or higher.

    
30.07.2016 / 17:58