Ich suche nach einer Möglichkeit, eine interne Datei mit dem FileProvider der Android Support Library korrekt für eine externe Anwendung freizugeben (nicht zu öffnen) .
Folgen Sie dem Beispiel in den Dokumenten,
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.supportv4.my_files"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_paths" />
</provider>
und Verwenden von ShareCompat zum Freigeben einer Datei für andere Apps wie folgt:
ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
funktioniert nicht, da FLAG_GRANT_READ_URI_PERMISSION nur die Berechtigung für den auf der data
Absicht angegebenen Uri erteilt , nicht den Wert des EXTRA_STREAM
Extra (wie von festgelegt setStream
).
Ich habe versucht, Kompromisse Sicherheit , indem android:exported
an true
für den Anbieter, sondern FileProvider
intern überprüft , ob sich exportiert wird, wenn dem so ist , wirft es eine Ausnahme.
android
android-contentprovider
android-support-library
android-fileprovider
Randy Sugianto 'Yuku'
quelle
quelle
Antworten:
Wenn
FileProvider
Sie die Support-Bibliothek verwenden, müssen Sie manuell (zur Laufzeit) Berechtigungen erteilen und widerrufen, damit andere Apps bestimmte Uri lesen können. Verwenden Sie die Methoden Context.grantUriPermission und Context.revokeUriPermission .Beispielsweise:
Als letzten Ausweg können Sie, wenn Sie keinen Paketnamen angeben können, allen Apps die Berechtigung erteilen, die bestimmte Absichten verarbeiten können:
Alternative Methode gemäß Dokumentation :
Übrigens. Bei Bedarf können Sie die Quelle von FileProvider kopieren und die
attachInfo
Methode ändern , um zu verhindern, dass der Anbieter überprüft, ob er exportiert wird.quelle
grantUriPermission
Methode müssen wir den Paketnamen der App angeben, für die wir die Berechtigung erteilen möchten. Bei der Freigabe wissen wir jedoch normalerweise nicht, welche Anwendung das Freigabeziel ist.Voll funktionsfähiges Codebeispiel zum Freigeben von Dateien aus dem inneren App-Ordner. Getestet auf Android 7 und Android 5.
AndroidManifest.xml
xml / provider_paths
Code selbst
quelle
ShareCompat.IntentBuilder
und der Lese-URI-Berechtigung hat es schließlich für mich getan.FileProvider
, die funktioniert. Bei den anderen Antworten wird die Absicht falsch behandelt (sie werden nicht verwendetShareCompat.IntentBuilder
), und diese Absicht kann von externen Apps in keiner sinnvollen Weise geöffnet werden. Ich habe buchstäblich den größten Teil des Tages mit diesem Unsinn verbracht, bis ich endlich deine Antwort gefunden habe.Diese Lösung funktioniert bei mir seit OS 4.4. Damit es auf allen Geräten funktioniert, habe ich eine Problemumgehung für ältere Geräte hinzugefügt. Dies stellt sicher, dass immer die sicherste Lösung verwendet wird.
Manifest.xml:
file_paths.xml:
Java:
Die Berechtigung wird mit revokeFileReadPermission () in den Methoden onResume und onDestroy () des Fragments oder der Aktivität widerrufen.
quelle
file
wird sich nicht vononResume
bis ändernonDestroy
?Da dies, wie Phil in seinem Kommentar zur ursprünglichen Frage sagt, einzigartig ist und es in Google keine weiteren Informationen zu SO gibt, dachte ich, ich sollte auch meine Ergebnisse teilen:
In meiner App hat FileProvider sofort Dateien mit der Freigabeabsicht freigegeben. Darüber hinaus war keine spezielle Konfiguration oder Code erforderlich, um den FileProvider einzurichten. In meine manifest.xml habe ich gesetzt:
In my_paths.xml habe ich:
In meinem Code habe ich:
Und ich kann meinen Dateispeicher im privaten Speicher meiner Apps problemlos mit Apps wie Google Mail und Google Drive teilen.
quelle
Soweit ich das beurteilen kann, funktioniert dies nur mit neueren Versionen von Android, sodass Sie wahrscheinlich einen anderen Weg finden müssen, dies zu tun. Diese Lösung funktioniert für mich unter 4.4, jedoch nicht unter 4.0 oder 2.3.3. Daher ist dies kein nützlicher Weg, um Inhalte für eine App freizugeben, die auf einem Android-Gerät ausgeführt werden soll.
In manifest.xml:
Beachten Sie sorgfältig, wie Sie die Behörden angeben. Sie müssen die Aktivität angeben, aus der Sie den URI erstellen und die Freigabeabsicht starten. In diesem Fall heißt die Aktivität SharingActivity. Diese Anforderung ist aus den Google-Dokumenten nicht ersichtlich!
file_paths.xml:
Seien Sie vorsichtig, wie Sie den Pfad angeben. Der obige Wert ist standardmäßig das Stammverzeichnis Ihres privaten internen Speichers.
In SharingActivity.java:
In diesem Beispiel teilen wir ein JPEG-Bild.
Schließlich ist es wahrscheinlich eine gute Idee, sich zu vergewissern, dass Sie die Datei ordnungsgemäß gespeichert haben und mit so etwas darauf zugreifen können:
quelle
In meiner App funktioniert FileProvider einwandfrei und ich kann interne Dateien, die im Dateiverzeichnis gespeichert sind, an E-Mail-Clients wie Google Mail, Yahoo usw. anhängen.
In meinem Manifest, wie in der Android-Dokumentation erwähnt, habe ich Folgendes platziert:
Und da meine Dateien im Stammdateiverzeichnis gespeichert wurden, lautete die Datei filepaths.xml wie folgt:
Jetzt im Code:
Das hat bei mir funktioniert. Hoffentlich hilft das :)
quelle
Wenn Sie ein Bild von der Kamera erhalten, funktioniert keine dieser Lösungen für Android 4.4. In diesem Fall ist es besser, die Versionen zu überprüfen.
quelle
Nur um die oben angegebene Antwort zu verbessern: Wenn Sie NullPointerEx erhalten:
Sie können getApplicationContext () auch ohne Kontext verwenden
quelle
Ich möchte etwas mitteilen, das uns für ein paar Tage blockiert hat: Der Dateiprovider-Code MUSS zwischen den Anwendungs-Tags eingefügt werden, nicht danach. Es mag trivial sein, aber es wird nie spezifiziert, und ich dachte, ich hätte jemandem helfen können! (Nochmals vielen Dank an piolo94)
quelle