Wenn eine App auf eine Datei zugreifen möchte, die von einer anderen App freigegeben wurde, wird die anfragende App (der Client)
sendet normalerweise eine Anfrage an die App, die die Dateien freigibt (den Server). In den meisten Fällen
startet ein Activity
in der Server-App, das die Dateien anzeigt, die freigegeben werden können.
Der Nutzer wählt eine Datei aus, woraufhin die Server-App den Inhalts-URI der Datei an den
Client-App.
In dieser Lektion erfahren Sie, wie eine Client-App eine Datei von einer Server-App anfordert, die Inhalts-URI aus der Server-App und öffnet die Datei mit dem Inhalts-URI.
Anfrage für die Datei senden
Zum Anfordern einer Datei von der Server-App ruft die Client-App auf
startActivityForResult
mit einem
Intent
mit der Aktion, z. B.
ACTION_PICK
und einen MIME-Typ, den die Client-App
die Sie bewältigen können.
Das folgende Code-Snippet zeigt beispielsweise, wie ein
Intent
an eine Server-App, um den
Activity
beschrieben unter Datei freigeben:
Kotlin
class MainActivity : Activity() { private lateinit var requestFileIntent: Intent private lateinit var inputPFD: ParcelFileDescriptor ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) requestFileIntent = Intent(Intent.ACTION_PICK).apply { type = "image/jpg" } ... } ... private fun requestFile() { /** * When the user requests a file, send an Intent to the * server app. * files. */ startActivityForResult(requestFileIntent, 0) ... } ... }
Java
public class MainActivity extends Activity { private Intent requestFileIntent; private ParcelFileDescriptor inputPFD; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestFileIntent = new Intent(Intent.ACTION_PICK); requestFileIntent.setType("image/jpg"); ... } ... protected void requestFile() { /** * When the user requests a file, send an Intent to the * server app. * files. */ startActivityForResult(requestFileIntent, 0); ... } ... }
Auf die angeforderte Datei zugreifen
Die Server-App sendet den Inhalts-URI der Datei in einem
Intent
Diese Intent
wird an den Client übergeben.
durch onActivityResult()
überschrieben wird. Einmal
die Client-App den Inhalts-URI der Datei hat, kann sie auf die Datei zugreifen, indem sie
FileDescriptor
Die Dateisicherheit wird bei diesem Vorgang nur gewahrt, wenn Sie den Inhalts-URI richtig parsen die die Client-App erhält. Achten Sie beim Parsen von Inhalten darauf, dass dieser URI nicht auf nicht auf das vorgesehene Verzeichnis. Es wird versucht, einen Pfaddurchlauf zu erstellen. Nur die Client-App sollte Zugriff auf die Datei erhalten und nur die von der Server-App. Berechtigungen sind temporär. Sobald der Aufgabenstapel der Client-App fertig ist, auf die Datei kann nicht mehr außerhalb der Server-App zugegriffen werden.
Das nächste Snippet zeigt, wie die Client-App
Intent
wird von der Server-App gesendet und wie die Client-App die
FileDescriptor
mithilfe des Inhalts-URI:
Kotlin
/* * When the Activity of the app that hosts files sets a result and calls * finish(), this method is invoked. The returned Intent contains the * content URI of a selected file. The result code indicates if the * selection worked or not. */ public override fun onActivityResult(requestCode: Int, resultCode: Int, returnIntent: Intent) { // If the selection didn't work if (resultCode != Activity.RESULT_OK) { // Exit without doing anything else return } // Get the file's content URI from the incoming Intent returnIntent.data?.also { returnUri -> /* * Try to open the file for "read" access using the * returned URI. If the file isn't found, write to the * error log and return. */ inputPFD = try { /* * Get the content resolver instance for this context, and use it * to get a ParcelFileDescriptor for the file. */ contentResolver.openFileDescriptor(returnUri, "r") } catch (e: FileNotFoundException) { e.printStackTrace() Log.e("MainActivity", "File not found.") return } // Get a regular file descriptor for the file val fd = inputPFD.fileDescriptor ... } }
Java
/* * When the Activity of the app that hosts files sets a result and calls * finish(), this method is invoked. The returned Intent contains the * content URI of a selected file. The result code indicates if the * selection worked or not. */ @Override public void onActivityResult(int requestCode, int resultCode, Intent returnIntent) { // If the selection didn't work if (resultCode != RESULT_OK) { // Exit without doing anything else return; } else { // Get the file's content URI from the incoming Intent Uri returnUri = returnIntent.getData(); /* * Try to open the file for "read" access using the * returned URI. If the file isn't found, write to the * error log and return. */ try { /* * Get the content resolver instance for this context, and use it * to get a ParcelFileDescriptor for the file. */ inputPFD = getContentResolver().openFileDescriptor(returnUri, "r"); } catch (FileNotFoundException e) { e.printStackTrace(); Log.e("MainActivity", "File not found."); return; } // Get a regular file descriptor for the file FileDescriptor fd = inputPFD.getFileDescriptor(); ... } }
Die Methode openFileDescriptor()
gibt ParcelFileDescriptor
für die Datei zurück. Über dieses Objekt
App ein FileDescriptor
-Objekt erhält, mit dem sie dann die Datei lesen kann.
Weitere Informationen finden Sie hier: