Cannot open file:///.. URL in Capacitor Browser plugin in Android

I have a file://… URL that was generated using using Capacitor Filesystem.writeFile() method which I then passed in Capacitor Browser. However Android Studio throws a bunch of errors and crashes the app.

My intention is to open the image in the browser and thus providing an easy way for user to download the image manually as a workaround to the Android 13 restrictions on public storage.

Is this a possible thing to do?

const uriResult = await Filesystem.writeFile({
      path: fileName,
      data: base64,
      directory: Directory.Cache
});

//uriResult.uri = file:///data/user/0/io.ionic.starter/cache/test.jpg

Browser.open({
      url: uriResult.uri
});
E/Capacitor: Serious error executing plugin
    java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:138)
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$com-getcapacitor-Bridge(Bridge.java:767)
        at com.getcapacitor.Bridge$$ExternalSyntheticLambda5.run(Unknown Source:8)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: android.os.FileUriExposedException: file:///data/user/0/io.ionic.starter/cache/test.jpg exposed beyond app through Intent.getData()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:2083)
        at android.net.Uri.checkFileUriExposed(Uri.java:2388)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10791)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10744)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1703)
        at android.app.Activity.startActivityForResult(Activity.java:5192)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:647)
        at android.app.Activity.startActivityForResult(Activity.java:5150)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:628)
        at android.app.Activity.startActivity(Activity.java:5521)
        at androidx.core.content.ContextCompat$Api16Impl.startActivity(ContextCompat.java:830)
        at androidx.core.content.ContextCompat.startActivity(ContextCompat.java:279)
        at androidx.browser.customtabs.CustomTabsIntent.launchUrl(CustomTabsIntent.java:376)
        at com.capacitorjs.plugins.browser.Browser.open(Browser.java:112)
        at com.capacitorjs.plugins.browser.BrowserPlugin.open(BrowserPlugin.java:53)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:138) 
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$com-getcapacitor-Bridge(Bridge.java:767) 
        at com.getcapacitor.Bridge$$ExternalSyntheticLambda5.run(Unknown Source:8) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 
E/AndroidRuntime: FATAL EXCEPTION: CapacitorPlugins
    Process: io.ionic.starter, PID: 4376
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$com-getcapacitor-Bridge(Bridge.java:776)
        at com.getcapacitor.Bridge$$ExternalSyntheticLambda5.run(Unknown Source:8)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:138)
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$com-getcapacitor-Bridge(Bridge.java:767)
        at com.getcapacitor.Bridge$$ExternalSyntheticLambda5.run(Unknown Source:8) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 
     Caused by: android.os.FileUriExposedException: file:///data/user/0/io.ionic.starter/cache/test.jpg exposed beyond app through Intent.getData()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:2083)
        at android.net.Uri.checkFileUriExposed(Uri.java:2388)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10791)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10744)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1703)
        at android.app.Activity.startActivityForResult(Activity.java:5192)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:647)
        at android.app.Activity.startActivityForResult(Activity.java:5150)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:628)
        at android.app.Activity.startActivity(Activity.java:5521)
        at androidx.core.content.ContextCompat$Api16Impl.startActivity(ContextCompat.java:830)
        at androidx.core.content.ContextCompat.startActivity(ContextCompat.java:279)
        at androidx.browser.customtabs.CustomTabsIntent.launchUrl(CustomTabsIntent.java:376)
        at com.capacitorjs.plugins.browser.Browser.open(Browser.java:112)
        at com.capacitorjs.plugins.browser.BrowserPlugin.open(BrowserPlugin.java:53)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:138) 
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$com-getcapacitor-Bridge(Bridge.java:767) 
        at com.getcapacitor.Bridge$$ExternalSyntheticLambda5.run(Unknown Source:8) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 
I/Process: Sending signal. PID: 4376 SIG: 9

Update:

As stated, my intention was to open the image in the browser and thus providing an easy way for user to download the image manually as a workaround to the Android 13 restrictions on public storage.

It did not solve the issue in this thread but I managed to achieve my goal using GitHub - capacitor-community/media: Capacitor plugin to activate extra media features

As far as I know, the browser plugin cannot open local file paths.
If anyone else has a similar problem in the future, one of the following two plugins may help:

  1. Share
  2. File Opener

I use a combination of these plugins myself to open and save files in my app.

1 Like

@robingenz That’s too bad.

Yes i have definitely tried those two plugins before attempting the browser approach.

Unfortunately on Android the Capacitor Share plugin doesn’t have a “Save file” functionality like on iOS by default, which really could make things a lot easier. The only way I can get that option is by installing a third party file manager app.

The File Opener plugin opens the file and it has a Share button, which does the same thing.

That is correct. Under Android, you need a file manager to save the file. For my customers, this has not been a problem so far, because a file manager was pre-installed on their business devices, but this is not a perfect solution. I might create a plugin that allows you to save a file in a public download folder as soon as I need it.

2 Likes