Berechtigungsverweigerung beim Freigeben einer Datei mit FileProvider [duplicate]
Lesezeit: 6 Minuten
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)
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:
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:
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
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().
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
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));
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()
14388300cookie-checkBerechtigungsverweigerung beim Freigeben einer Datei mit FileProvider [duplicate]yes
stackoverflow.com/a/74052302/987762 für die Antwort
– Kalanar
13. Oktober 2022 um 8:04 Uhr