2

User click on .txt file in file explorer and get dialog "Open with..." and there is listed my app. When I try to open file I want to get its absolute path. All I get is content:// URI

I/ActivityManager: START u0 {act=android.intent.action.VIEW dat=content://com.android.providers.downloads.documents/document/1031 typ=text/plain

If I want to retrieve path to my file I need to get file:// URI. How can I get only file:// URI instead of content:// ?

Here is AndroidManifest

        <intent-filter >
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />    
            <data android:mimeType="text/*"/>
        </intent-filter>

Here is how I try to handle file:

Intent i = getIntent();
String action = i.getAction();
String type = i.getType();

if (Intent.ACTION_VIEW.equals(action) && type != null) {
    Uri uri = i.getData();
    if (uri != null) {
        Toast.makeText(this, uri.toString(), Toast.LENGTH_SHORT).show();
    }                 
}
Personal Jesus
  • 133
  • 2
  • 10

1 Answers1

2

Here is AndroidManifest

Your <intent-filter> is saying that you can handle text/* content no matter where it comes from.

When I try to open file I want to get its absolute path

Then you need to add <data android:scheme="file"> to your <intent-filter>, to declare that you only work with file schemes. Your app will no longer appear as an option in apps that do not use file Uri values, such as the "file manager" that you are using. And, since file Uri values are effectively banned on Android 7.0+, your app will be less useful over time. By 2020 or so, your app will be useless.

Or, you could get rid of the "want to get its absolute path" requirement. If you want to retrieve the text content from a file or a content Uri, you can use openInputStream() on a ContentResolver, for example.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • But I want not only read file, I also want to edit file and save. – Personal Jesus Jun 15 '17 at 12:39
  • @PersonalJesus: There is `openOutputStream()`, also on `ContentResolver`. IOW, the same things that you would do with an absolute path and `FileInputStream`/`FileOutputStream` are things that you can do with a `content` `Uri` and `openInputStream()`/`openOutputStream()`. – CommonsWare Jun 15 '17 at 12:55
  • @CommonsWare LibVLC Player Library for Android doesn't support Content Uri, it needs absolute path, because it's a native library (c++, c) and it doesn't know nothing about that stuff! – user25 Feb 09 '19 at 15:10
  • @user25: Then only work with files. Use [a file chooser library](https://android-arsenal.com/tag/35?sort=created) instead of something that gives you a `content` `Uri`. – CommonsWare Feb 09 '19 at 15:12
  • @CommonsWare a file chooser? We're talking about `ACTION_VIEW`. I have an app - Video Player. I want to open a video file in this app from some other app - Explorer app, e.g. https://play.google.com/store/apps/details?id=com.speedsoftware.explorer – user25 Feb 09 '19 at 15:13
  • @CommonsWare Alsi I see that before Android 7 it returns absolute path of file, but starting from Android 7 it returns content uri string – user25 Feb 09 '19 at 15:16
  • @user25: Then don't use LibVLC. Or convince the authors of LibVLC to support non-seekable `InputStreams`, so you can use `ContentResolver` and `openInputStream()`. Or copy the content from the `Uri` to a file that you control. Or limit your `ACTION_VIEW` `` to `file` schemes. Or eliminate your `ACTION_VIEW` `` and have users open files within your app using a file chooser library, as I suggested earlier. – CommonsWare Feb 09 '19 at 15:18
  • @CommonsWare Official "VLC for Android" app (and many others) somehow bypassed this issue. I just need to find out how they did it. https://play.google.com/store/apps/details?id=org.videolan.vlc – user25 Feb 09 '19 at 15:29
  • @CommonsWare `non-seekable InputStreams` what is that? – user25 Feb 09 '19 at 15:30
  • @user25: You cannot assume that an `InputStream` from `openInputStream()` on a `ContentResolver` supports `mark()` and `reset()` to move backwards in the stream. It works with file-backed streams, but not all `content` streams will be backed by files on the filesystem. "Official "VLC for Android" app... somehow bypassed this issue" -- only by crashing, based on my experience. For example, I have to copy content from removable storage to the device, as VLC crashes when trying to work with removable storage directly. – CommonsWare Feb 09 '19 at 15:34
  • @CommonsWare I mean everything was working fine before Android 7. We could get absolute file path from intent and do with it whatever we want. But now there is such problem. Does Google developers forget about Native stuff (C++)? – user25 Feb 09 '19 at 15:39
  • @user25: "We could get absolute file path from intent" -- only if you limited your `` to support the `file` scheme. If you supported the `content` scheme and attempted to "convert" the `Uri` to a filesystem path, your code always had bugs and would fail with various sources of content. It so happens that the likelihood that you get `content` increases significantly on newer versions of Android. "Does Google developers forget about Native stuff (C++)?" -- no, but they expect you to work with `content` correctly, which will limit your options. – CommonsWare Feb 09 '19 at 15:42
  • @CommonsWare I copied all intent-filters from official VLC project. Now I tried to remove `` and it started to work fine. But in which cases do they need to support `content` scheme? How or which apps send this `scheme` to their app? Or how to use both `file` and `content` schemes but set higher priority for `file` scheme: when I open a file from explorer app I want to get `file` scheme if it's available – user25 Feb 09 '19 at 15:51
  • @user25: "But in which cases they need to support content scheme?" -- `file` `Uri` values are effectively banned on Android 7.0+ for apps with a high `targetSdkVersion`. See [this blog post](https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html) (while it refers to the N Developer Preview, nothing really changed when Android 7.0 shipped). "Or how to use both file and content schemes but set higher priority for file scheme" -- an `ACTION_VIEW` `Intent` only has one `Uri` and one scheme, so I don't see how a priority system would work. – CommonsWare Feb 09 '19 at 15:53