Skip to content

[Bug]: Shared files on Android are read-only (Share plugin) #2268

Open
@khokholikov

Description

@khokholikov

Capacitor Version

💊 Capacitor Doctor 💊

Latest Dependencies:

@capacitor/cli: 6.1.2
@capacitor/core: 6.1.2
@capacitor/android: 6.1.2
@capacitor/ios: 6.1.2

Installed Dependencies:

@capacitor/ios: not installed
@capacitor/cli: 6.1.2
@capacitor/core: 6.1.2
@capacitor/android: 6.1.2

[success] Android looking great! 👌

Other API Details

npm --version: 10.9.0
node --version: v20.15.0

Platforms Affected

  • iOS
  • Android
  • Web

Current Behavior

If I share a file with url parameter and then try to save my changes to the file with an external app I get the following error on Android API 35:
image

Permission Denial: writing androidx.core.content.FileProvider uri content://com.example.fileprovider/files/dbtables.txt from pid=16876, uid=10212 requires the provider be exported, or grantUriPermission()

I think everything in AndroidManifest.xml and file_paths.xml is ok:

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="files" path="." />
    ...
</paths>

I am sure because after making the proposed change (see "Additional information" section) the error disappears. And this change is not some hack, it is quite logical.

This is the js call (src/pages/IndexPage.vue):

<q-list bordered separator class="col-10 text-center">
      <q-item v-for="file in fileList" :key="file.uri" clickable v-ripple>
        <q-item-section @click="share(file)">
          {{ file.name }}
        </q-item-section>
      </q-item>
    </q-list>
const share = async (file: FileInfo) => {
  await Share.share({
    url: file.uri,
  });
};

Expected Behavior

I would like to share the file from my app in such a way that the third-party application can make changes to the file. For instance, if I share a docx-document saved in my app I would expect the third-party text editor to be able to edit the file and save it in-place instead of first saving a copy of the file in another place and then sharing it back with my application to overwrite the file with the updated version.

Project Reproduction

https://github.com/khokholikov/capacitor.git

Run quasar dev -m capacitor -T android, upload an editable file, then select the file in the list under the upload file input and try to edit this file and save from another application.

Additional Information

I propose a solution to either 1) append Intent.FLAG_GRANT_WRITE_URI_PERMISSION to intent.setFlags() call in src-capacitor/node_modules/@capacitor/share/android/src/main/java/com/capacitorjs/plugins/share/SharePlugin.java or 2) add a parameter to Share.share() function call where you could set whether the share is read-only or writable.

The first variant would be: intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

The second variant maybe is a little bit more flexible, for instance, if you want to be able to share only a copy of the file.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions