-2

I am trying to open the file downloaded by DownloadManager. I registered a BroadcastReceiver with action DownloadManager.ACTION_DOWNLOAD_COMPLETE.

Here's the onReceive method of my receiver-

try {
    DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);

    DownloadManager.Query query = new DownloadManager.Query();
    query.setFilterById(downloadId);

    Cursor c = dm != null ? dm.query(query) : null;
    Log.d("Cursor", String.valueOf(c));
    String uri = null;
    if (c != null && c.moveToFirst()) {
        uri = c.getString(c.getColumnIndex("local_uri"));
    }
    Log.d("URI", uri);

    Intent open = new Intent(Intent.ACTION_VIEW);
    open.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    //Get mime type
    String mimeType = "*/*";
    String extension = null;
    extension = MimeTypeMap.getFileExtensionFromUrl(uri);
    if (extension != null) {
        mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }

    //Set data and start activity  
    open.setDataAndType(FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", new File(Uri.parse(uri).getPath())), mimeType);    //It shows error at this line 
    startActivity(install);
} catch (Exception e) {
    e.printStackTrace();
}  

Here is the provider tag in my AndroidManifest.xml file -

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>  

And the provider_paths.xml file -

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path
        name="external_files"
        path="/"/>
</paths>  

But when I run my app, it shows this error when it tries to open the file:
java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/... (the uri)

The complete stack trace looks like this :

01-14 20:49:49.069 21296-21296/in.edu.jaduniv.classroom W/System.err: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Classroom/juit1620/Syllabus/1405929814-1-14.pdf
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:719)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:404)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at in.edu.jaduniv.classroom.activity.Syllabus$2.onReceive(Syllabus.java:149)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1122)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.os.Handler.handleCallback(Handler.java:751)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.os.Looper.loop(Looper.java:154)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6123)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
01-14 20:49:49.070 21296-21296/in.edu.jaduniv.classroom W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
01-14 20:50:21.336 21296-21358/in.edu.jaduniv.classroom W/DynamiteModule: Local module descriptor class for com.google.firebase.auth not found.
01-14 20:54:02.582 21296-23083/in.edu.jaduniv.classroom D/FA: Logging event (FE): user_engagement(_e), Bundle[{firebase_event_origin(_o)=auto, engagement_time_msec(_et)=338004, firebase_screen_class(_sc)=Syllabus, firebase_screen_id(_si)=-6138131816728422160}]
01-14 20:54:02.611 21296-23083/in.edu.jaduniv.classroom D/FA: Connected to remote service

What should I do?
Thanks!

Rishav Agarwal
  • 96
  • 1
  • 11

1 Answers1

4

Replace new File(uri) with new File(Uri.parse(uri).getPath()) in your FileProvider.getUriForFile() call. The value that you get from local_uri appears to be a Uri, with a file scheme.

Also, depending upon the rest of the Uri, you may need to replace external-files-path with external-path.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • The new statement looks like this - `install.setDataAndType(FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", new File(Uri.parse(uri).getPath())), mimeType);` – Rishav Agarwal Jan 14 '18 at 15:25
  • @RishavAgarwal: Please update your question to show the complete Java stack trace associated with your current crash. – CommonsWare Jan 14 '18 at 15:25
  • I have updated the question with your answer and the stack trace – Rishav Agarwal Jan 14 '18 at 15:30
  • 1
    @RishavAgarwal: Your file is not in `getExternalFilesDir()`, so `external-files-path` is incorrect. Replace `external-files-path` with `external-path` in your `provider_paths.xml` file. – CommonsWare Jan 14 '18 at 15:33
  • I was wondering why new File(Uri.parse(uri).getPath()) worked? – Rishav Agarwal Jan 15 '18 at 04:24
  • 1
    @RishavAgarwal: Your `Uri` is of the form `file:/storage/emulated/0/this/is/some/path/to/something.txt`. A `Uri` cannot be saved directly in a database or file; its string representation is saved. So, you originally get back a string representation of that `Uri`. `Uri.parse()` gives you the `Uri`. `getPath()` on the `Uri` gives you the path portion of the `Uri`, which for the `file` scheme is pretty much everything but the scheme (e.g., `/storage/emulated/0/this/is/some/path/to/something.txt`). `new File()` converts that path into a `File`. – CommonsWare Jan 15 '18 at 11:38