pwlin / cordova-plugin-file-opener2

A File Opener Plugin for Cordova
MIT License
314 stars 587 forks source link

android 8.1 errorcode #225

Closed zhaoleisam closed 5 years ago

zhaoleisam commented 6 years ago

error: file:///storage/emulated/0/test.apk exposed beyond app through Intent.getData()

zhaoleisam commented 6 years ago

Error status: undefined - Error message: undefined

juristr commented 6 years ago

Getting the same.

var pathToFile = cordova.file.cacheDirectory + downloadData.filename;
              window['resolveLocalFileSystemURL'](
                pathToFile,
                function(entry) {
                  cordova.plugins.fileOpener2.open(entry.toInternalURL(), 'application/pdf', {
                    error: function(e) {
                      console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
                    },
                    success: function() {
                      console.log('file opened successfully');
                    }
                  });
                },
                function(e) {
                  console.log('File Not Found');
                }
              );

The file is stored successfully, but trying to open it results in an error

godoyrw commented 6 years ago

Look this: https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed

juristr commented 6 years ago

@godoyrw Hmm...in fact, I added this

<provider android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider" android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
</provider>

based on your comment here: https://github.com/pwlin/cordova-plugin-file-opener2/issues/220#issuecomment-410464846. Didn't help though...

Right now I'm trying

this.fileOpener.open(x.toInternalURL(), downloadData.mimeType)

where x is a fileEntry saved to the externalCacheDirectory. It works perfectly on Android 5.x but fails on Android 8+...

zhaoleisam commented 6 years ago

we will set targetSdkVersion = 23 this question will be solved

juristr commented 6 years ago

Sure, but that might not be an option.

@godoyrw the log says this:

1:42.162 6096-6096/? D/MediaScannerReceiver: action: android.intent.action.MEDIA_SCANNER_SCAN_FILE path: /storage/emulated/0/Android/data/com.myapp.demo/cache/Scheda località-1.000A-2018_8_29 (1).pdf
08-30 16:11:42.213 7723-7809/com.myapp.demo E/PluginManager: Uncaught exception from plugin
                                                                  java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
                                                                      at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:604)
                                                                      at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:578)
                                                                      at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:416)
                                                                      at io.github.pwlin.cordova.plugins.fileopener2.FileOpener2._open(FileOpener2.java:110)
                                                                      at io.github.pwlin.cordova.plugins.fileopener2.FileOpener2.execute(FileOpener2.java:67)
                                                                      at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:98)
                                                                      at org.apache.cordova.PluginManager.exec(PluginManager.java:132)
                                                                      at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:57)
                                                                      at org.apache.cordova.engine.SystemExposedJsApi.exec(SystemExposedJsApi.java:41)
                                                                      at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
                                                                      at org.chromium.base.SystemMessageHandler.handleMessage(SourceFile:9)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                      at android.os.Looper.loop(Looper.java:164)
                                                                      at android.os.HandlerThread.run(HandlerThread.java:65)

any idea?

zhaoleisam commented 6 years ago

but,I see this progect source code ,the author added the FileProvider method.

juristr commented 6 years ago

My config.xml looks as follows..should be fine as far as I understand

<preference name="android-minSdkVersion" value="19" />
<preference name="android-targetSdkVersion" value="28" />
<platform name="android">
    <provider android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider" android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
    </provider>
    <preference name="server-path" value="/app2/mobile" />
    <preference name="AndroidPersistentFileLocation" value="Internal" />
    <config-file parent="/manifest" target="AndroidManifest.xml" xmlns:android="http://schemas.android.com/apk/res/android">
        <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.SEND_SMS" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-feature android:name="android.hardware.telephony" android:required="false" />
    </config-file>
   ...
</platform>

and just for being complete 😅 , the URL with which I invoke the file opener is the following:

"cdvfile://localhost/cache-external/Scheda%20localita%CC%80-1.000A-2018_8_29%20(1).pdf"
zhaoleisam commented 6 years ago

In My project , if you add this plugin,these settings will be automatically set in the XML file

juristr commented 6 years ago

Currently debugging the code where the NullPointerException is thrown..

update

Sadly the exception happens inside the android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:604). The passed params inside the FileOpener2.java class seem to look good.. 🤔

juristr commented 6 years ago

fixed it! 🎉 Doing some final checks and then I'll submit a PR!

zhaoleisam commented 6 years ago

how do you do this

godoyrw commented 6 years ago

Hi, guys, Hi, did you guys work it out?

juristr commented 6 years ago

Yep, so what I did is to

// import io.github.pwlin.cordova.plugins.fileopener2.FileProvider;
import android.support.v4.content.FileProvider;

and then change this line

https://github.com/pwlin/cordova-plugin-file-opener2/blob/681d39b140c9d4ae0d8c8f68000515e16ebb9eba/src/android/io/github/pwlin/cordova/plugins/fileopener2/FileOpener2.java#L114

to the following:

path = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);

No need to register a separate provider in the manifest file. Here's the local patch that seems to work on Android 5.x as well as v8+: https://gist.github.com/juristr/96826576d88e2cf6187ef32dbccee5aa

That seemed to solve my issue, still checking whether I changed something else as well. But btw, I just wanted to submit a PR and recognized that the current version of the FileOpener2.java in master is different than the one I get when installing the latest version 2.0.19 !?

// @pwlin

juristr commented 6 years ago

Another of my doubts is that since I'm using Cordova to build, that the Cordova's config.xml is not properly merged into the Android manifest xml and thus misses the FileOpener2 provider registration. I think I checked that, but gonna verify in more details probably today.

@godoyrw @zhaoleisam Let me know if patching it like this also solves your issues. @pwlin still maintaining this lib? What do you think about the solution? I can submit a PR in case

godoyrw commented 6 years ago

@juristr #Uhuuuuu I was not in trouble, I always try to help here. I use this Lib too in some projects! Your solution was very good! I think there's a BugFix in Lib's GIT on this, you should post there!

juristr commented 6 years ago

Alright, so double-checked again, and (damned) it seems like the main issue was that the provider from FileOpener2 wasn't properly registered in my AndroidManifest.xml. During installation of the plugin it was there, but then when compiling the Cordova app, it got removed again.

So, having this in my AndroidManifest.xml

<provider android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths"/>
    </provider>

...seems to work. So if you run into this issue, make sure it's there and it hasn't been removed.

vvarda commented 6 years ago
  1. Changed: import io.github.pwlin.cordova.plugins.fileopener2.FileProvider; to import android.support.v4.content.FileProvider;Doesn't work on Android 8.1

  2. Changed: path = FileProvider.getUriForFile(context, cordova.getActivity().getPackageName() + ".opener.provider", file); to path = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", file);

  3. That code is present in AndroidManifest.xml:

    <provider android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths"/>
    </provider>

But, doesn't work on Android 8.1: error handler with Failed to find configured root that contains /data/data/<app_bundler_id>/cache/<document.pdf>

BorntraegerMarc commented 5 years ago

Fixed it by adding the following config in my ionic project in the config.xml file:

        <config-file parent="/manifest/application" target="AndroidManifest.xml">
            <provider android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
                <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
            </provider>
        </config-file>
vvarda commented 5 years ago

Fixed it by adding the following config in my ionic project in the config.xml file:

        <config-file parent="/manifest/application" target="AndroidManifest.xml">
            <provider android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
                <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
            </provider>
        </config-file>

Which cordova-android version is installed? It doesn't work on 7.1.1: UnhandledPromiseRejectionWarning: TypeError: Path must be a string. Received undefined

Also, it's not necessary, because that snippet is present in AndroidManifest.xml after adding the plugin

<provider android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true" android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
  <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
</provider>

@juristr any ideas?

BorntraegerMarc commented 5 years ago

@vvarda for me that snipped didn't get copied through the plugin. I'm using cordova-android v7.1.1

TinyChou commented 5 years ago

we will set targetSdkVersion = 23 this question will be solved

works well now.

klochko7 commented 5 years ago

I have the same error on android 8 using latest version 2.0.19 !

exposed beyond app through intent.getdata()

shnist commented 5 years ago

hi @klochko7, try using version 2.1.0, that included a number of android related fixes.

shnist commented 5 years ago

Closing this issue due to inactivity. Feel free to reopen if this is still an issue.