Geteilte Datei anfordern

Wenn eine Anwendung auf eine Datei zugreifen möchte, die von einer anderen Anwendung freigegeben wurde, sendet die anfragende Anwendung (der Client) in der Regel eine Anfrage an die Anwendung, die die Dateien teilt (den Server). In den meisten Fällen startet die Anfrage ein Activity in der Serveranwendung, in der die Dateien angezeigt werden, die freigegeben werden können. Der Nutzer wählt eine Datei aus. Anschließend gibt die Server-App den Inhalts-URI der Datei an die Client-App zurück.

In dieser Lektion erfahren Sie, wie eine Clientanwendung eine Datei von einer Serveranwendung anfordert, den Inhalts-URI der Datei von der Serveranwendung empfängt und die Datei mit dem Inhalts-URI öffnet.

Dateianfrage senden

Zum Anfordern einer Datei von der Serveranwendung ruft die Clientanwendung startActivityForResult mit einer Intent auf, die die Aktion enthält, z. B. ACTION_PICK, und einen MIME-Typ, den die Clientanwendung verarbeiten kann.

Das folgende Code-Snippet zeigt beispielsweise, wie ein Intent an eine Serveranwendung gesendet wird, um die unter Datei freigeben beschriebene Activity zu starten:

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 an die Client-App zurück. Dieser Intent wird in der Überschreibung von onActivityResult() an die Client-App übergeben. Sobald die Client-App den Inhalts-URI der Datei hat, kann sie über die FileDescriptor auf die Datei zugreifen.

Die Dateisicherheit bleibt bei diesem Vorgang erhalten, da der Inhalts-URI das einzige Datenelement ist, das die Clientanwendung empfängt. Da dieser URI keinen Verzeichnispfad enthält, kann die Client-App keine anderen Dateien in der Server-App erkennen und öffnen. Nur die Client-App erhält Zugriff auf die Datei, und nur die Berechtigungen, die von der Server-App gewährt werden. Die Berechtigungen sind temporär. Sobald der Aufgaben-Stack der Client-App abgeschlossen ist, ist die Datei außerhalb der Server-App nicht mehr zugänglich.

Das nächste Snippet zeigt, wie die Client-App das von der Serveranwendung gesendete Intent verarbeitet und wie die Client-App das FileDescriptor über den Inhalts-URI abruft:

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 ein ParcelFileDescriptor für die Datei zurück. Von diesem Objekt erhält die Client-App ein FileDescriptor-Objekt, mit dem sie dann die Datei lesen kann.

Weitere Informationen finden Sie hier: