Search code examples
androidexceptionstoragesd-card

IllegalStateException on phone with SD while using DownloadManager


I got a report on the Play Store of an ANR on my app.

Here's the stacktrace:

java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)

Caused by: java.lang.IllegalStateException: Unable to create directory: /storage/sdcard0/storage/external_SD/Video
at android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.java:496)
at com.pipodi.italiansubsmobileclient.connections.ConnectionForSubtitle.doInBackground(ConnectionForSubtitle.java:61)
at com.pipodi.italiansubsmobileclient.connections.ConnectionForSubtitle.doInBackground(ConnectionForSubtitle.java:21)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 5 more

Here's the code:

SharedPreferences preferences = MainActivity.context.getSharedPreferences(Constants.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
    String path = preferences.getString("DOWNLOADDIR", null);
    this.directory = "";
    try {
        directory = path.replace(Environment.getExternalStorageDirectory().getCanonicalPath(), "");
    } catch (IOException e) {
        e.printStackTrace();
    }
    File direct = new File(path);
    if (!direct.exists()) {
        direct.mkdirs();
    }
    DownloadManager mgr = (DownloadManager) MainActivity.context
            .getSystemService(Context.DOWNLOAD_SERVICE);
    Uri downloadUri = Uri
            .parse("https://api.italiansubs.net/api/rest/subtitles/download?subtitle_id="
                    + this.id
                    + "&authcode="
                    + somecodehere
                    + "&apikey="
                    + Constants.APIKey);
    DownloadManager.Request request = new DownloadManager.Request(
            downloadUri);
    List<Cookie> loginCookies = LoginVariables.loginCookies;
    request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI
                    | DownloadManager.Request.NETWORK_MOBILE)
            .setAllowedOverRoaming(false)
            .setTitle("Download sottotitoli")
            .setDescription(fileName)
            .setDestinationInExternalPublicDir(directory,
                    fileName + ".zip");
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    String cookieString = "";
    for (Cookie cookie : loginCookies) {
        cookieString += cookie.getName() + "=" + cookie.getValue() + "; path=" + cookie.getPath()
                + "; domain=" + cookie.getDomain() + "; expiry=" + cookie.getExpiryDate() + "; ";
    }
    request.addRequestHeader("Cookie", cookieString);
    mgr.enqueue(request);
    return null;

The line getting the exception is this:

request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI
                    | DownloadManager.Request.NETWORK_MOBILE)
            .setAllowedOverRoaming(false)
            .setTitle("Download sottotitoli")
            .setDescription(fileName)
            .setDestinationInExternalPublicDir(directory,
                    fileName + ".zip");

It seems that, on a phone with an external SD card, the app throws an exception. I told the user to try saving the file on the internal storage of the phone and the download was completed succesfully. Now, I couldn't manage to create an AVD emulating a phone with an SD card, so I'm here asking you this question.

On the Manifest there is this permission:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Do I need to give the app also the permission to read the external storage, or what?

The device is a LG Optimus L5 II (vee5nfc) running Android 4.1.

Thanks for the help, guys.


Solution

  • At the end I solved the issue. I think it was an OS version-related problem: the minimum version was 4.x, but I fixed the error putting it to 4.3.1.