How to download Webview files from the Sdcard if available

Asked

Viewed 397 times

1

The App is a simple browser that works like Webview. This code makes the files to be downloaded into 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 they’re going for the cell phone memory. If your phone has a Sdcard inserted, how do I get the files to be downloaded directly to Sdcard?

  • This is to run on that version of Android(minimum version)?

  • It’s running at 2.3... minimum SDK 9...

  • Why it has to be on Sdcard?

  • Because most cell phones have little internal memory.

  • Are you sure you’re recording on the inside? What is the model of the device you tested?

  • Yes I do! I tested on G2 and G3 and LG-E410F

  • You are wearing request.setDestinationInExternalPublicDir() which, as the name implies would be external memory. The problem is that newer devices may have more than one type of external memory. Besides the Sdcard, they may have some internal(fixed) considered with external. As I have never used the Downloadmanager I don’t know if that’s the problem. Now I don’t have time, tomorrow I’ll give you an answer to test.

  • That may be! I await your answer!

Show 3 more comments

1 answer

0


You are wearing 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 external memory. Besides the Sdcard, they may have some internal (fixed) considered as external.

The fact that minSdk is 9 limits somewhat the way of obtaining, with a guarantee, the path for Sdcard, so I do not guarantee that the following 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);

for

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 the fixed. In the Samsung Galaxy Tab3(4.4.2) returned the two.
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 later.

  • Tested on the G3 bike, it almost worked: The problem was that it saved in the wrong place there on sdcard, example: "sdcard/Android/name.do.package/files/" was like this. Already in android less than 5.1 seems not to work even.

  • This is the right location, is the one that is assigned by android for your application(Note the part .../nome.do.pacote/...).

  • No way to put the root of the SD Card?

  • The problem is knowing the "root" name, it may vary according to the level/brand/model API. Think about the case where a user switches to another device and wants to continue using your application with the same sdcard, he will no longer have access to old downloads (at least the application will).

  • Got it. I’ll consider your answer, you can Help others you want like this. But this way it doesn’t pay for my application! You have already helped me a lot and I am grateful to you! Thank you very much!

  • If you have any further questions ask a new question, I will try to help.

  • Do you think it’s hard to do that business of granting permission for Android 6.0? (for me I’m beginner)

  • Look at this reply

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.