Über freigegebenen Speicher auf Dokumente und andere Dateien zugreifen

Auf Geräten mit Android 4.4 (API-Level 19) und höher kann Ihre App über das Storage Access Framework mit einem Dokumentenanbieter interagieren, einschließlich externer Speichervolumes und cloudbasierten Speichers. Dieses Framework ermöglicht es Nutzern, mit einer Systemauswahl zu interagieren einen Dokumentenanbieter und bestimmte Dokumente und andere Dateien App erstellen, öffnen oder ändern können.

Da der Nutzer an der Auswahl der Dateien oder Verzeichnisse beteiligt ist, die Ihre Anwendung Zugriff haben, ist für diesen Mechanismus kein System Berechtigungen, Nutzersteuerung und Datenschutz optimiert ist. Außerdem werden diese Dateien, die außerhalb eines App-spezifisches Verzeichnis und außerhalb des Media Stores auf dem Gerät verbleiben. nachdem Ihre App deinstalliert wurde.

Die Verwendung des Frameworks umfasst die folgenden Schritte:

  1. Eine Anwendung ruft einen Intent auf, der eine speicherbezogene Aktion enthält. Diese Aktion entspricht einem spezifischen Anwendungsfall, den das Framework erstellt. verfügbar.
  2. Der Nutzer sieht eine Systemauswahl, über die er nach einem Dokumentanbieter suchen kann und wählen Sie einen Speicherort oder ein Dokument aus, an dem die speicherbezogene Aktion stattfindet.
  3. Die App erhält Lese- und Schreibzugriff auf einen URI, der die Variable Speicherort oder Dokument ausgewählt. Mithilfe dieses URI kann die App Vorgänge auf den ausgewählten Standort.

Um den Zugriff auf Mediendateien auf Geräten mit Android 9 (API-Level 28) oder niedriger ist, deklarieren Sie die READ_EXTERNAL_STORAGE und legen Sie maxSdkVersion auf 28 fest.

In diesem Leitfaden werden die verschiedenen Anwendungsfälle beschrieben, die das Framework für die Arbeit mit Dateien und anderen Dokumenten unterstützt. Außerdem wird erläutert, wie Sie Vorgänge am vom Nutzer ausgewählten Standort ausführen.

Anwendungsfälle für den Zugriff auf Dokumente und andere Dateien

Das Storage Access Framework unterstützt die folgenden Anwendungsfälle für den Zugriff auf und andere Dokumente.

Neue Datei erstellen
Die ACTION_CREATE_DOCUMENT Intent-Aktion ermöglicht es Nutzern, eine Datei an einem bestimmten Ort zu speichern.
Dokumente oder Dateien öffnen
Die ACTION_OPEN_DOCUMENT Intent-Aktion ermöglicht es Nutzern, ein bestimmtes Dokument oder eine bestimmte Datei zum Öffnen auszuwählen.
Zugriff auf den Inhalt eines Verzeichnisses gewähren
Die Intent-Aktion ACTION_OPEN_DOCUMENT_TREE, die unter Android 5.0 (API-Level 21) und höher verfügbar ist, ermöglicht es Nutzern, ein bestimmtes Verzeichnis auszuwählen und Ihrer App Zugriff auf alle Dateien und Unterverzeichnisse in diesem Verzeichnis zu gewähren.

In den folgenden Abschnitten finden Sie Anleitungen zur Konfiguration der einzelnen Anwendungsfälle.

Neue Dateien erstellen

Verwenden Sie die Intent-Aktion ACTION_CREATE_DOCUMENT, um die Systemdateiauswahl zu laden und dem Nutzer die Möglichkeit zu geben, einen Speicherort für das Schreiben des Inhalts einer Datei auszuwählen. Dieser Vorgang ähnelt dem, der in den Dialogfeldern „Als Datei speichern“ anderer Betriebssysteme verwendet wird.

Hinweis: ACTION_CREATE_DOCUMENT kann den Wert vorhandener Datei. Wenn Ihre App versucht, eine Datei mit demselben Namen zu speichern, fügt das System am Ende des Dateinamens eine Zahl in Klammern hinzu.

Wenn Ihre App beispielsweise versucht, eine Datei namens confirmation.pdf in einem Verzeichnis zu speichern, das bereits eine Datei mit diesem Namen enthält, speichert das System die neue Datei mit dem Namen confirmation(1).pdf.

Geben Sie beim Konfigurieren des Intents den Namen und den MIME-Typ der Datei an und geben Sie optional den URI der Datei oder des Verzeichnisses an, das die Dateiauswahl beim ersten Laden anzeigen soll. Verwenden Sie dazu das Intent-Extra EXTRA_INITIAL_URI.

Das folgende Code-Snippet zeigt, wie der Intent zum Erstellen einer Datei erstellt und aufgerufen wird:

// Request code for creating a PDF document.
const val CREATE_FILE = 1

private fun createFile(pickerInitialUri: Uri) {
    val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "application/pdf"
        putExtra(Intent.EXTRA_TITLE, "invoice.pdf")

        // Optionally, specify a URI for the directory that should be opened in
        // the system file picker before your app creates the document.
        putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
    }
    startActivityForResult(intent, CREATE_FILE)
}
// Request code for creating a PDF document.
private static final int CREATE_FILE = 1;

private void createFile(Uri pickerInitialUri) {
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("application/pdf");
    intent.putExtra(Intent.EXTRA_TITLE, "invoice.pdf");

    // Optionally, specify a URI for the directory that should be opened in
    // the system file picker when your app creates the document.
    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);

    startActivityForResult(intent, CREATE_FILE);
}

Datei öffnen

Ihre App verwendet möglicherweise Dokumente als Speichereinheit, in die Nutzer Daten eingeben. die sie mit Kollegen teilen oder in andere Dokumente importieren möchten. Mehrere z. B. wenn Nutzende ein Produktivitätsdokument öffnen oder ein Buch öffnen, als EPUB-Datei gespeichert.

In diesen Fällen kann der Nutzer die zu öffnende Datei auswählen, indem er die ACTION_OPEN_DOCUMENT Intent erstellt, die die Dateiauswahl-App des Systems öffnet. Um nur die Typen von -Dateien, die von Ihrer App unterstützt werden, geben Sie einen MIME-Typ an. Außerdem können Sie optional gibt den URI der Datei an, die in der Dateiauswahl angezeigt werden soll, wenn sie das erste Mal angezeigt wird mit der Methode EXTRA_INITIAL_URI zusätzliche Absicht.

Im folgenden Code-Snippet sehen Sie, wie der Intent zum Öffnen PDF-Dokument:

// Request code for selecting a PDF document.
const val PICK_PDF_FILE = 2

fun openFile(pickerInitialUri: Uri) {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "application/pdf"

        // Optionally, specify a URI for the file that should appear in the
        // system file picker when it loads.
        putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
    }

    startActivityForResult(intent, PICK_PDF_FILE)
}
// Request code for selecting a PDF document.
private static final int PICK_PDF_FILE = 2;

private void openFile(Uri pickerInitialUri) {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("application/pdf");

    // Optionally, specify a URI for the file that should appear in the
    // system file picker when it loads.
    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);

    startActivityForResult(intent, PICK_PDF_FILE);
}

Zugriffsbeschränkungen

Unter Android 11 (API-Level 30) und höher können Sie die Intent-Aktion ACTION_OPEN_DOCUMENT nicht verwenden, um den Nutzer aufzufordern, einzelne Dateien aus den folgenden Verzeichnissen auszuwählen:

  • Das Verzeichnis Android/data/ und alle Unterverzeichnisse.
  • Das Verzeichnis Android/obb/ und alle Unterverzeichnisse

Zugriff auf den Inhalt eines Verzeichnisses gewähren

Apps zur Dateiverwaltung und zum Erstellen von Medien verwalten Dateien in der Regel in einem Verzeichnishierarchie. Um diese Funktion in Ihrer App bereitzustellen, verwenden Sie den ACTION_OPEN_DOCUMENT_TREE Intent-Aktion, mit der der Nutzer Zugriff auf ein ganzes Verzeichnis gewähren kann Baumstruktur, mit einigen Ausnahmen ab Android 11 (API-Level 30). Ihre App kann und greifen Sie dann auf eine beliebige Datei im ausgewählten Verzeichnis und in seinen Unterverzeichnissen zu.

Wenn Sie ACTION_OPEN_DOCUMENT_TREE verwenden, erhält Ihre App nur Zugriff auf die Dateien im Verzeichnis, das der Nutzer auswählt. Sie haben keinen Zugriff auf Dateien anderer Apps, die sich außerhalb dieses vom Nutzer ausgewählten Verzeichnisses befinden. Dieses ermöglicht es den Nutzenden, genau auszuwählen, mit Ihrer App teilen möchten.

Optional können Sie den URI des Verzeichnisses angeben, das in der Dateiauswahl angezeigt werden soll. mit der Methode EXTRA_INITIAL_URI zusätzliche Absicht.

Im folgenden Code-Snippet sehen Sie, wie der Intent zum Öffnen ein Verzeichnis:

fun openDirectory(pickerInitialUri: Uri) {
    // Choose a directory using the system's file picker.
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
        // Optionally, specify a URI for the directory that should be opened in
        // the system file picker when it loads.
        putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
    }

    startActivityForResult(intent, your-request-code)
}
public void openDirectory(Uri uriToLoad) {
    // Choose a directory using the system's file picker.
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);

    // Optionally, specify a URI for the directory that should be opened in
    // the system file picker when it loads.
    intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriToLoad);

    startActivityForResult(intent, your-request-code);
}

Zugriffsbeschränkungen

Unter Android 11 (API-Level 30) und höher können Sie die Intent-Aktion ACTION_OPEN_DOCUMENT_TREE nicht verwenden, um Zugriff auf die folgenden Verzeichnisse anzufordern:

  • Das Stammverzeichnis des internen Speicher-Volumes.
  • Das Stammverzeichnis jedes SD-Karten-Volumes, das vom Gerätehersteller als zuverlässig erachtet wird, unabhängig davon, ob die Karte emuliert oder abnehmbar. Ein zuverlässiges Volume ist ein Volume, auf das eine App die meisten Inhalte zugreifen kann. die Uhrzeit.
  • Das Verzeichnis Download.

Außerdem können Sie unter Android 11 (API-Level 30) und höher nicht über die Intent-Aktion ACTION_OPEN_DOCUMENT_TREE den Nutzer auffordern, einzelne Dateien aus den folgenden Verzeichnissen auszuwählen:

  • Das Verzeichnis Android/data/ und alle Unterverzeichnisse.
  • Das Verzeichnis Android/obb/ und alle Unterverzeichnisse

Vorgänge für den ausgewählten Standort ausführen

Nachdem der Nutzer eine Datei oder ein Verzeichnis über die Dateiauswahl des Systems ausgewählt hat, können Sie den URI des ausgewählten Elements mit dem folgenden Code in onActivityResult():

override fun onActivityResult(
        requestCode: Int, resultCode: Int, resultData: Intent?) {
    if (requestCode == your-request-code
            && resultCode == Activity.RESULT_OK) {
        // The result data contains a URI for the document or directory that
        // the user selected.
        resultData?.data?.also { uri ->
            // Perform operations on the document using its URI.
        }
    }
}
@Override
public void onActivityResult(int requestCode, int resultCode,
        Intent resultData) {
    if (requestCode == your-request-code
            && resultCode == Activity.RESULT_OK) {
        // The result data contains a URI for the document or directory that
        // the user selected.
        Uri uri = null;
        if (resultData != null) {
            uri = resultData.getData();
            // Perform operations on the document using its URI.
        }
    }
}

Wenn Sie einen Verweis auf den URI des ausgewählten Elements abrufen, kann Ihre App mehrere Operationen für das Element. Sie können beispielsweise auf die Metadaten des Elements zugreifen, das Element an Ort und Stelle bearbeiten und es löschen.

In den folgenden Abschnitten wird beschrieben, wie Sie Aktionen an den vom Nutzer ausgewählten Dateien ausführen.

Von einem Anbieter unterstützte Vorgänge ermitteln

Unterschiedliche Inhaltsanbieter ermöglichen unterschiedliche Aktionen an Dokumenten, z. B. das Kopieren des Dokuments oder das Ansehen der Miniaturansicht eines Dokuments. Welche Vorgänge ein bestimmter Anbieter unterstützt, geht aus dem Wert von Document.COLUMN_FLAGS hervor. Die Benutzeroberfläche Ihrer App kann dann nur die Optionen anzeigen, die der Anbieter unterstützt.

Berechtigungen beibehalten

Wenn Ihre App eine Datei zum Lesen oder Schreiben öffnet, weist das System Ihrer App URI-Berechtigung für diese Datei gewährt, bis das Gerät des Nutzers neu gestartet. Angenommen, Ihre App ist eine Bildbearbeitungs-App und Sie möchten können Nutzer direkt auf die fünf Bilder zugreifen, die sie zuletzt bearbeitet haben. aus Ihrer App. Wurde das Gerät des Nutzers neu gestartet, zur Systemauswahl zurückkehren, um die Dateien zu finden.

Damit der Zugriff auf Dateien nach einem Neustart des Geräts erhalten bleibt und die Nutzerfreundlichkeit verbessert wird, kann Ihre App die vom System angebotene dauerhafte URI-Berechtigung annehmen, wie im folgenden Code-Snippet gezeigt:

val contentResolver = applicationContext.contentResolver

val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
        Intent.FLAG_GRANT_WRITE_URI_PERMISSION
// Check for the freshest data.
contentResolver.takePersistableUriPermission(uri, takeFlags)
final int takeFlags = intent.getFlags()
            & (Intent.FLAG_GRANT_READ_URI_PERMISSION
            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);

Dokumentmetadaten prüfen

Wenn Sie den URI für ein Dokument haben, erhalten Sie Zugriff auf dessen Metadaten. Dieses Snippet ruft die Metadaten für ein Dokument ab, das durch den URI angegeben ist, und protokolliert sie:

val contentResolver = applicationContext.contentResolver

fun dumpImageMetaData(uri: Uri) {

    // The query, because it only applies to a single document, returns only
    // one row. There's no need to filter, sort, or select fields,
    // because we want all fields for one document.
    val cursor: Cursor? = contentResolver.query(
            uri, null, null, null, null, null)

    cursor?.use {
        // moveToFirst() returns false if the cursor has 0 rows. Very handy for
        // "if there's anything to look at, look at it" conditionals.
        if (it.moveToFirst()) {

            // Note it's called "Display Name". This is
            // provider-specific, and might not necessarily be the file name.
            val displayName: String =
                    it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME))
            Log.i(TAG, "Display Name: $displayName")

            val sizeIndex: Int = it.getColumnIndex(OpenableColumns.SIZE)
            // If the size is unknown, the value stored is null. But because an
            // int can't be null, the behavior is implementation-specific,
            // and unpredictable. So as
            // a rule, check if it's null before assigning to an int. This will
            // happen often: The storage API allows for remote files, whose
            // size might not be locally known.
            val size: String = if (!it.isNull(sizeIndex)) {
                // Technically the column stores an int, but cursor.getString()
                // will do the conversion automatically.
                it.getString(sizeIndex)
            } else {
                "Unknown"
            }
            Log.i(TAG, "Size: $size")
        }
    }
}
public void dumpImageMetaData(Uri uri) {

    // The query, because it only applies to a single document, returns only
    // one row. There's no need to filter, sort, or select fields,
    // because we want all fields for one document.
    Cursor cursor = getActivity().getContentResolver()
            .query(uri, null, null, null, null, null);

    try {
        // moveToFirst() returns false if the cursor has 0 rows. Very handy for
        // "if there's anything to look at, look at it" conditionals.
        if (cursor != null && cursor.moveToFirst()) {

            // Note it's called "Display Name". This is
            // provider-specific, and might not necessarily be the file name.
            String displayName = cursor.getString(
                    cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
            Log.i(TAG, "Display Name: " + displayName);

            int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
            // If the size is unknown, the value stored is null. But because an
            // int can't be null, the behavior is implementation-specific,
            // and unpredictable. So as
            // a rule, check if it's null before assigning to an int. This will
            // happen often: The storage API allows for remote files, whose
            // size might not be locally known.
            String size = null;
            if (!cursor.isNull(sizeIndex)) {
                // Technically the column stores an int, but cursor.getString()
                // will do the conversion automatically.
                size = cursor.getString(sizeIndex);
            } else {
                size = "Unknown";
            }
            Log.i(TAG, "Size: " + size);
        }
    } finally {
        cursor.close();
    }
}

Dokument öffnen

Wenn Sie einen Verweis auf den URI eines Dokuments haben, können Sie es zur weiteren Verarbeitung öffnen. Dieser Abschnitt enthält Beispiele zum Öffnen einer Bitmap und einer Eingabe. .

Bitmap

Im folgenden Code-Snippet sehen Sie, wie ein Bitmap-Datei mit ihrem URI:

val contentResolver = applicationContext.contentResolver

@Throws(IOException::class)
private fun getBitmapFromUri(uri: Uri): Bitmap {
    val parcelFileDescriptor: ParcelFileDescriptor =
            contentResolver.openFileDescriptor(uri, "r")
    val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor
    val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
    parcelFileDescriptor.close()
    return image
}
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
    ParcelFileDescriptor parcelFileDescriptor =
            getContentResolver().openFileDescriptor(uri, "r");
    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
    parcelFileDescriptor.close();
    return image;
}

Nachdem Sie die Bitmap geöffnet haben, können Sie sie ImageView

Eingabestream

Im folgenden Code-Snippet wird gezeigt, wie ein InputStream-Objekt anhand seiner URI geöffnet wird. In diesem Snippet werden die Zeilen der Datei in einen String gelesen:

val contentResolver = applicationContext.contentResolver

@Throws(IOException::class)
private fun readTextFromUri(uri: Uri): String {
    val stringBuilder = StringBuilder()
    contentResolver.openInputStream(uri)?.use { inputStream ->
        BufferedReader(InputStreamReader(inputStream)).use { reader ->
            var line: String? = reader.readLine()
            while (line != null) {
                stringBuilder.append(line)
                line = reader.readLine()
            }
        }
    }
    return stringBuilder.toString()
}
private String readTextFromUri(Uri uri) throws IOException {
    StringBuilder stringBuilder = new StringBuilder();
    try (InputStream inputStream =
            getContentResolver().openInputStream(uri);
            BufferedReader reader = new BufferedReader(
            new InputStreamReader(Objects.requireNonNull(inputStream)))) {
        String line;
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
        }
    }
    return stringBuilder.toString();
}

Dokumente bearbeiten

Mit dem Storage Access Framework können Sie ein Textdokument direkt bearbeiten.

Mit dem folgenden Code-Snippet wird der Inhalt des dargestellten Dokuments überschrieben. durch den angegebenen URI:

val contentResolver = applicationContext.contentResolver

private fun alterDocument(uri: Uri) {
    try {
        contentResolver.openFileDescriptor(uri, "w")?.use {
            FileOutputStream(it.fileDescriptor).use {
                it.write(
                    ("Overwritten at ${System.currentTimeMillis()}\n")
                        .toByteArray()
                )
            }
        }
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }
}
private void alterDocument(Uri uri) {
    try {
        ParcelFileDescriptor pfd = getActivity().getContentResolver().
                openFileDescriptor(uri, "w");
        FileOutputStream fileOutputStream =
                new FileOutputStream(pfd.getFileDescriptor());
        fileOutputStream.write(("Overwritten at " + System.currentTimeMillis() +
                "\n").getBytes());
        // Let the document provider know you're done by closing the stream.
        fileOutputStream.close();
        pfd.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Dokument löschen

Wenn Sie den URI für ein Dokument und die Document.COLUMN_FLAGS enthält SUPPORTS_DELETE, können Sie das Dokument löschen. Beispiel:

DocumentsContract.deleteDocument(applicationContext.contentResolver, uri)
DocumentsContract.deleteDocument(applicationContext.contentResolver, uri);

Äquivalente Medien-URI abrufen

Die getMediaUri() stellt einen Medienspeicher-URI bereit, der den angegebenen Dokumenten entspricht. Anbieter-URI. Die beiden URIs verweisen auf dasselbe zugrunde liegende Element. Mit dem URI des Medienspeichers können Sie einfacher auf Mediendateien aus freigegebenem Speicher zugreifen.

Die Methode getMediaUri() unterstützt ExternalStorageProvider-URIs. An Android 12 (API-Level 31) und höher unterstützt die Methode auch MediaDocumentsProvider URIs.

Virtuelle Datei öffnen

Unter Android 7.0 (API-Level 25) und höher kann Ihre App virtuelle Dateien verwenden, die vom Storage Access Framework bereitgestellt werden. Auch wenn virtuelle Dateien keine binäre Darstellung haben, kann Ihre App ihren Inhalt öffnen, indem sie in einen anderen Dateityp umgewandelt oder mithilfe der Intent-Aktion ACTION_VIEW angezeigt werden.

Zum Öffnen virtueller Dateien muss Ihre Client-App eine spezielle Logik für die Verarbeitung . Wenn Sie eine Bytedarstellung der Datei erhalten möchten, z. B. für eine Vorschau, müssen Sie beim Dokumentanbieter einen alternativen MIME-Typ anfordern.

Nachdem der Nutzer eine Auswahl getroffen hat, kannst du anhand des URI in den Ergebnisdaten feststellen, ob die Datei virtuell ist, wie im folgenden Code-Snippet gezeigt:

private fun isVirtualFile(uri: Uri): Boolean {
    if (!DocumentsContract.isDocumentUri(this, uri)) {
        return false
    }

    val cursor: Cursor? = contentResolver.query(
            uri,
            arrayOf(DocumentsContract.Document.COLUMN_FLAGS),
            null,
            null,
            null
    )

    val flags: Int = cursor?.use {
        if (cursor.moveToFirst()) {
            cursor.getInt(0)
        } else {
            0
        }
    } ?: 0

    return flags and DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT != 0
}
private boolean isVirtualFile(Uri uri) {
    if (!DocumentsContract.isDocumentUri(this, uri)) {
        return false;
    }

    Cursor cursor = getContentResolver().query(
        uri,
        new String[] { DocumentsContract.Document.COLUMN_FLAGS },
        null, null, null);

    int flags = 0;
    if (cursor.moveToFirst()) {
        flags = cursor.getInt(0);
    }
    cursor.close();

    return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
}

Nachdem Sie überprüft haben, dass es sich bei dem Dokument um eine virtuelle Datei handelt, können Sie das in einen alternativen MIME-Typ wie "image/png" umwandeln. Im folgenden Code-Snippet wird gezeigt, wie geprüft wird, ob eine virtuelle Datei als Bild dargestellt werden kann, und falls ja, wird ein Eingabestream aus der virtuellen Datei abgerufen:

@Throws(IOException::class)
private fun getInputStreamForVirtualFile(
        uri: Uri, mimeTypeFilter: String): InputStream {

    val openableMimeTypes: Array<String>? =
            contentResolver.getStreamTypes(uri, mimeTypeFilter)

    return if (openableMimeTypes?.isNotEmpty() == true) {
        contentResolver
                .openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null)
                .createInputStream()
    } else {
        throw FileNotFoundException()
    }
}
private InputStream getInputStreamForVirtualFile(Uri uri, String mimeTypeFilter)
    throws IOException {

    ContentResolver resolver = getContentResolver();

    String[] openableMimeTypes = resolver.getStreamTypes(uri, mimeTypeFilter);

    if (openableMimeTypes == null ||
        openableMimeTypes.length < 1) {
        throw new FileNotFoundException();
    }

    return resolver
        .openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null)
        .createInputStream();
}

Weitere Informationen

Weitere Informationen zum Speichern und Zugriff auf Dokumente und andere Dateien finden Sie in den folgenden Ressourcen.

Produktproben

Videos