Berechtigungsverweigerung beim Freigeben einer Datei mit FileProvider [duplicate]

Lesezeit: 6 Minuten

Benutzeravatar von Paweł Bęza
Paweł Bęza

Ich versuche, eine Datei mit FileProvider zu teilen. Ich habe überprüft, ob die Datei ordnungsgemäß mit Apps wie Google Mail, Google Drive usw. geteilt wird. Obwohl die folgende Ausnahme ausgelöst wird:

2019-08-28 11:43:03.169 12573-12595/com.example.name E/DatabaseUtils: Writing exception to parcel
    java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.example.name.provider/external_files/Android/data/com.example.name/files/allergy_report.pdf from pid=6005, uid=1000 requires the provider be exported, or grantUriPermission()
        at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:729)
        at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:602)
        at android.content.ContentProvider$Transport.query(ContentProvider.java:231)
        at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:104)
        at android.os.Binder.execTransactInternal(Binder.java:1021)
        at android.os.Binder.execTransact(Binder.java:994)

Anbieter:

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

file_provider_paths.xml

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

Absicht teilen

Intent intentShareFile = new Intent(Intent.ACTION_SEND);
File fileWithinMyDir = new File(targetPdf);

if (fileWithinMyDir.exists()) {
    intentShareFile.setType("application/pdf");
    Uri uri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", fileWithinMyDir);
    intentShareFile.putExtra(Intent.EXTRA_STREAM, uri);
    intentShareFile.putExtra(Intent.EXTRA_SUBJECT, "Sharing File...");
    intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
    intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(Intent.createChooser(intentShareFile, "Share File"));
}

Hoffentlich können Sie auf meinen Fehler hinweisen, warum diese Ausnahmen ausgelöst werden, wenn es so aussieht, als ob Apps die Berechtigung ordnungsgemäß erteilt wird und das Teilen so funktioniert, wie es sein sollte.

BEARBEITEN:

Ich habe festgestellt, dass das Problem in der Zeile liegt:

startActivity(Intent.createChooser(intentShareFile, "Share File"));

Als ich es einfach umgestellt habe

startActivity(intentShareFile);

Es zeigt jedoch ein etwas anderes Layout für die Kommissionieranwendung. Aber ich kann immer noch nicht herausfinden, warum Original Chooser nicht funktioniert.

  • stackoverflow.com/a/74052302/987762 für die Antwort

    – Kalanar

    13. Oktober 2022 um 8:04 Uhr

Sorry für die späte Antwort. Ich habe es so gelöst:

Intent chooser = Intent.createChooser(intentShareFile, "Share File");

List<ResolveInfo> resInfoList = this.getPackageManager().queryIntentActivities(chooser, PackageManager.MATCH_DEFAULT_ONLY);

for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    this.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

startActivity(chooser);

Das hat mir geholfen: Berechtigungsverweigerung mit Dateianbieter durch Absicht

  • Großartig! Schlüssel zum Mitnehmen, den ich anfangs verpasst habe: Übergeben Sie die Auswahl, nicht die Absicht, abzufragenIntentActivities()

    – Lukas Hansen

    23. Februar 2020 um 21:34 Uhr


  • OMG, ich beschäftige mich seit Tagen damit! Das hat mein Problem gelöst und ich habe keine Ahnung, warum ich es einfach kopiert und eingefügt habe, haha. Ich werde mir durchlesen, was gerade meinen Hintern gerettet hat! Vielen Dank!

    – NoobCoderChick

    24. Februar 2020 um 4:43 Uhr

  • Seltsam ist, dass ich 4 Bildansichten für dieselbe Aktivität habe und wenn Sie auf die erste klicken (eine davon), wird die Kamera-App angezeigt, Sie nehmen das Bild auf und es speichert in der Bildansicht ganz gut … die zweite I Klicken Sie, die Kamera wird angezeigt, Sie nehmen das Bild auf und wenn Sie das Häkchen auswählen, stürzt die App ab. Was auch super seltsam ist, ist, dass die Pfaddatei in Android-Dokumenten nicht funktioniert und ich “/” als Pfad verwenden muss … idk

    – NoobCoderChick

    24. Februar 2020 um 4:45 Uhr

  • Und was ist mit intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); wo Uris ist ArrayList?

    – t0m

    16. Dezember 2020 um 11:08 Uhr

  • Dies funktioniert für Ziel 31

    – iadcialim24

    17. April 2022 um 9:38 Uhr

Nits Benutzeravatar
Nit

Es gibt auch eine Möglichkeit, die URI-Berechtigung über das Intent-Flag zu erteilen, ohne manuell mit eingreifen zu müssen grantUriPermission() und durch Beibehaltung der Verwendung von Intent.createChooser().

Die Intent.createChooser() Dokumentation heißt es:

Wenn die Zielabsicht FLAG_GRANT_READ_URI_PERMISSION oder FLAG_GRANT_WRITE_URI_PERMISSION angegeben hat, werden diese Flags auch in der zurückgegebenen Auswahlabsicht gesetzt, wobei ihre ClipData entsprechend gesetzt wird: entweder eine direkte Widerspiegelung von getClipData(), wenn diese nicht null ist, oder eine neue ClipData, die daraus erstellt wird Daten bekommen().

Wenn also die ursprüngliche Absicht den Uri-Satz in sich hat ClipData oder hinein setData()sollte wie gewünscht funktionieren.

In Ihrem Beispiel ist die ACTION_SEND Absicht unterstützt den Uri-Satz durch setClipData() ab Jelly Bean (Android 4.1).

Lange Rede kurzer Sinn, hier ist ein funktionierendes Beispiel für Ihren Code:

Intent intentShareFile = new Intent(Intent.ACTION_SEND);
File fileWithinMyDir = new File(targetPdf);

if(fileWithinMyDir.exists()) {
    String mimeType = "application/pdf";
    String[] mimeTypeArray = new String[] { mimeType };
    
    intentShareFile.setType(mimeType);
    Uri uri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", fileWithinMyDir);
    
    // Add the uri as a ClipData
    intentShareFile.setClipData(new ClipData(
        "A label describing your file to the user",
        mimeTypeArray,
        new ClipData.Item(uri)
    ));
    
    // EXTRA_STREAM is kept for compatibility with old applications
    intentShareFile.putExtra(Intent.EXTRA_STREAM, uri);
    
    intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
            "Sharing File...");
    intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
    intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(Intent.createChooser(intentShareFile, "Share File"));
}

  • Vielen Dank! Perfekte Lösung ohne Abfrageaktivitäten.

    – Derek K

    19. Februar 2021 um 9:00 Uhr

  • Was ist der path benutzt in ClipData.Item ? Ich habe es versucht uri.pathaber die Ausnahme ist noch vorhanden.

    – Samuel T. Chou

    16. Februar 2022 um 8:35 Uhr

  • Ups, mein böser @SamuelT.Chou, das solltest du direkt setzen Uri beim Erstellen der ClipData.Item(). Ich habe meine Antwort mit dem Fix bearbeitet.

    – Nit

    17. Februar 2022 um 9:31 Uhr


Benutzeravatar von Harmen
Harmen

Zusätzlich zu der Antwort von Nit oben ist es möglich, das einzustellen ClipData direkt mit dem geteilt werden uri wie folgt.

intent.setClipData(ClipData.newRawUri("", uri));

Dadurch wird die Sicherheitsausnahme beim Anzeigen der Absichtsauswahl verhindert.

Wenn Sie mehrere URIS freigeben möchten, können Sie die Clipdata mit mehreren URIS festlegen, um die Sicherheitsausnahme zu verhindern. Zusammenfassen:


Intent intent = new Intent();
intent.setType(mimeType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

if (uris.size() == 0) { 
   return;
}
else if (uris.size() == 1) {
   Uri uri = uris.get(0);
   intent.setAction(Intent.ACTION_SEND);
   intent.putExtra(Intent.EXTRA_STREAM, uri);
   intent.setClipData(ClipData.newRawUri("", uri));   
}
else {
  intent.setAction(Intent.ACTION_SEND_MULTIPLE);
  intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
  ClipData clipData = ClipData.newRawUri("", uris.get(0));

  for (int i = 1; i < uris.size(); i++) { 
      Uri uri = uris.get(i); 
      clipData.addItem(new ClipData.Item(uri));
  }
  intent.setClipData(clipData);

}

startActivity(Intent.createChooser(intent, title));

Benutzeravatar von MOHO LEARNIN G
MOHO LERNEN G

Das hat bei mir funktioniert.

    Intent sharableIntent = new Intent();
    sharableIntent.setAction(Intent.ACTION_SEND);
    sharableIntent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION );

    Uri imageUri = Uri.parse(ImgLoc);
    File imageFile = new File(String.valueOf(imageUri));
    Uri UriImage = FileProvider.getUriForFile(context, Author, imageFile);

    sharableIntent.setType("image/*");
    sharableIntent.putExtra(Intent.EXTRA_STREAM, UriImage);
    sharableIntent.putExtra(Intent.EXTRA_TITLE, title);
    sharableIntent.putExtra(Intent.EXTRA_TEXT, body);

    Intent chooser = Intent.createChooser(sharableIntent, "Chooser Title");
    chooser.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
    context.startActivity(chooser);

createChooser
Intent.createChooser(): Erstellt einen neuen ACTION_CHOOSER-Intent, der den angegebenen Ziel-Intent umschließt und optional auch einen Titel bereitstellt. Wenn die Zielabsicht FLAG_GRANT_READ_URI_PERMISSION oder FLAG_GRANT_WRITE_URI_PERMISSION angegeben hat, werden diese Flags auch in der zurückgegebenen Auswahlabsicht gesetzt, wobei ihre ClipData entsprechend gesetzt wird: entweder eine direkte Widerspiegelung von getClipData(), wenn diese nicht null ist, oder eine neue ClipData, die daraus erstellt wird Daten bekommen()

1438830cookie-checkBerechtigungsverweigerung beim Freigeben einer Datei mit FileProvider [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy