Selektor zdjęć

Pojawi się selektor zdjęć z plikami multimedialnymi na urządzeniu. Wybierz zdjęcie, które chcesz udostępnić aplikacji.
Rysunek 1. Selektor zdjęć udostępnia intuicyjny interfejs do udostępniania zdjęć aplikacji.

Selektor zdjęć udostępnia interfejs, który umożliwia przeglądanie biblioteki multimediów użytkownika posortowanej według daty od najnowszych do najstarszych. Jak pokazano w ćwiczeniu z zakresu sprawdzonych metod ochrony prywatności, selektor zdjęć zapewnia użytkownikom bezpieczny, wbudowany sposób przyznawania aplikacji dostępu tylko do wybranych obrazów i filmów, a nie do całej biblioteki multimediów.

Użytkownicy, którzy mają na urządzeniu kwalifikujących się dostawców multimediów w chmurze, mogą też wybierać zdjęcia i filmy przechowywane zdalnie. Więcej informacji o dostawcach multimediów w chmurze

Narzędzie aktualizuje się automatycznie, a z upływem czasu będzie można oferować użytkownikom lepsze funkcje bez konieczności wprowadzania zmian w kodzie.

Używanie kontraktów Jetpack Activity

Aby uprościć integrację z selektorem zdjęć, dołącz bibliotekę androidx.activity w wersji 1.7.0 lub nowszą.

Aby uruchomić selektor zdjęć, użyj tych kontraktów wyników aktywności:

Jeśli selektor zdjęć nie jest dostępny na urządzeniu, biblioteka automatycznie wywołuje działanie intencji ACTION_OPEN_DOCUMENT. Ta intencja jest obsługiwana na urządzeniach z Androidem 4.4 (poziom interfejsu API 19) lub nowszym. Możesz sprawdzić, czy selektor zdjęć jest dostępny na danym urządzeniu, wywołując metodę isPhotoPickerAvailable().

Wybieranie pojedynczego elementu multimedialnego

Aby wybrać pojedynczy element multimedialny, użyj kontraktu wyniku aktywności PickVisualMedia, jak pokazano w tym fragmencie kodu:

Wyświetlenia

// Registers a photo picker activity launcher in single-select mode.
val pickMedia = registerForActivityResult(PickVisualMedia()) { uri ->
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: $uri")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

// Launch the photo picker and let the user choose only images.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
val mimeType = "image/gif"
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))

Wyświetlenia

// Registers a photo picker activity launcher in single-select mode.
ActivityResultLauncher<PickVisualMediaRequest> pickMedia =
        registerForActivityResult(new PickVisualMedia(), uri -> {
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: " + uri);
    } else {
        Log.d("PhotoPicker", "No media selected");
    }
});

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only images.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageOnly.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.VideoOnly.INSTANCE)
        .build());

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
String mimeType = "image/gif";
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(new PickVisualMedia.SingleMimeType(mimeType))
        .build());

Utwórz

// Registers a photo picker activity launcher in single-select mode.
val pickMedia = rememberLauncherForActivityResult(PickVisualMedia()) { uri ->
    // Callback is invoked after the user selects a media item or closes the
    // photo picker.
    if (uri != null) {
        Log.d("PhotoPicker", "Selected URI: $uri")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// Include only one of the following calls to launch(), depending on the types
// of media that you want to let the user choose from.

// Launch the photo picker and let the user choose images and videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

// Launch the photo picker and let the user choose only images.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))

// Launch the photo picker and let the user choose only videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))

// Launch the photo picker and let the user choose only images/videos of a
// specific MIME type, such as GIFs.
val mimeType = "image/gif"
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))

Zaznaczanie wielu elementów multimedialnych

Aby wybrać kilka elementów multimedialnych, ustaw maksymalną liczbę plików multimedialnych, które można wybrać, jak pokazano w tym fragmencie kodu.

Wyświetlenia

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
val pickMultipleMedia =
        registerForActivityResult(PickMultipleVisualMedia(5)) { uris ->
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (uris.isNotEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: ${uris.size}")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

Wyświetlenia

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
ActivityResultLauncher<PickVisualMediaRequest> pickMultipleMedia =
        registerForActivityResult(new PickMultipleVisualMedia(5), uris -> {
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (!uris.isEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: " + uris.size());
    } else {
        Log.d("PhotoPicker", "No media selected");
    }
});

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE)
        .build());

Utwórz

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app lets the user select up to 5 media files.
val pickMultipleMedia =
        rememberLauncherForActivityResult(PickMultipleVisualMedia(5)) { uris ->
    // Callback is invoked after the user selects media items or closes the
    // photo picker.
    if (uris.isNotEmpty()) {
        Log.d("PhotoPicker", "Number of items selected: ${uris.size}")
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

// For this example, launch the photo picker and let the user choose images
// and videos. If you want the user to select a specific type of media file,
// use the overloaded versions of launch(), as shown in the section about how
// to select a single media item.
pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

Platforma ogranicza maksymalną liczbę plików, które użytkownik może wybrać w selektorze zdjęć. Aby uzyskać dostęp do tego limitu, zadzwoń pod numer getPickImagesMaxLimit(). Na urządzeniach, na których selektor zdjęć nie jest obsługiwany, ten limit jest ignorowany.

Dostępność urządzeń

Selektor zdjęć jest dostępny na urządzeniach, które spełniają te kryteria:

Na starszych urządzeniach z Androidem w wersji od 4.4 (poziom interfejsu API 19) do 10 (poziom interfejsu API 29) oraz urządzeniach Android Go z Androidem 11 lub 12, które obsługują Usługi Google Play, można zainstalować wstecznie przeportowaną wersję selektora zdjęć. Aby włączyć automatyczną instalację wstecznie przeportowanego modułu selektora zdjęć za pomocą Usług Google Play, dodaj ten wpis do tagu <application> w pliku manifestu aplikacji:

<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
         android:enabled="false"
         android:exported="false"
         tools:ignore="MissingClass">
    <intent-filter>
        <action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
    </intent-filter>
    <meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>

Utrzymywanie dostępu do plików multimedialnych

Domyślnie system przyznaje aplikacji dostęp do plików multimedialnych do momentu ponownego uruchomienia urządzenia lub zatrzymania aplikacji. Jeśli aplikacja wykonuje długotrwałe zadania, takie jak przesyłanie dużego pliku w tle, może być konieczne zachowanie tego dostępu przez dłuższy czas. Aby to zrobić, wywołaj metodę takePersistableUriPermission():

Kotlin

val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flag)

Java

int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION;
context.contentResolver.takePersistableUriPermission(uri, flag);

Obsługa filmów HDR z transkodowaniem

W Androidzie 13 (API 33) wprowadzono możliwość nagrywania filmów High Dynamic Range (HDR). HDR zapewnia lepsze wrażenia wizualne, ale niektóre starsze aplikacje mogą nie obsługiwać tych nowszych formatów, co może prowadzić do problemów, takich jak nienaturalne odwzorowanie kolorów podczas odtwarzania (np. twarze z zielonym odcieniem). Aby rozwiązać ten problem ze zgodnością, selektor zdjęć oferuje funkcję transkodowania, która może automatycznie konwertować filmy HDR na format standardowego zakresu dynamiki (SDR) przed udostępnieniem ich aplikacji, która o nie prosi.

Głównym celem transkodowania w selektorze zdjęć jest zapewnienie spójnego i wizualnie dokładnego odtwarzania multimediów w szerszym zakresie aplikacji, nawet tych, które nie obsługują jeszcze HDR. Dzięki transkodowaniu filmów HDR do SDR selektor zdjęć ma na celu poprawę zgodności aplikacji i zapewnienie użytkownikom bezproblemowej obsługi.

Jak działa transkodowanie w selektorze zdjęć

Transkodowanie HDR w selektorze zdjęć nie jest domyślnie włączone. Aby włączyć tę funkcję, aplikacja musi wyraźnie zadeklarować możliwości obsługi formatów multimediów podczas uruchamiania selektora zdjęć.

Aplikacja udostępnia selektorowi zdjęć swoje możliwości przetwarzania multimediów. Można to zrobić podczas uruchamiania selektora zdjęć za pomocą biblioteki AndroidX Activity, dodając mediaCapabilities do PickVisualMediaRequest.Builder. Aby to ułatwić, do PickVisualMediaRequest.Builder dodaliśmy nowy interfejs API: setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?).

Zachowaniem transkodowania HDR możesz sterować za pomocą klasy MediaCapabilities. Podaj obiekt MediaCapabilities, który dokładnie określa, jakie typy HDR obsługuje Twoja aplikacja (np. TYPE_HLG10, TYPE_HDR10, TYPE_HDR10_PLUS, TYPE_DOLBY_VISION).

Aby całkowicie wyłączyć transkodowanie, przekaż null dla MediaCapabilities. Każdy typ HDR, który nie jest wyraźnie wymieniony w podanych przez Ciebie możliwościach, będzie uznawany za nieobsługiwany. Ten interfejs API jest obsługiwany na Androidzie 13 (API na poziomie 33) i nowszym i jest oznaczony adnotacją @RequiresApi(Build.VERSION_CODES.TIRAMISU).

import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.annotation.RequiresApi
import android.os.Build
import android.util.Log
import android.provider.MediaStore

// Registers a photo picker activity launcher.
val pickMedia = registerForActivityResult(PickVisualMedia()) { uri ->
    // Callback invoked after media selected or picker activity closed.
    if (uri != null) {
        Log.d("photo picker", "Selected URI: $uri")
    } else {
        Log.d("photo picker", "No media selected")
    }
}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun launchPhotoPickerWithTranscodingSupport() {
    val mediaCapabilities = MediaCapabilities.Builder()
        .addSupportedHdrType(MediaCapabilities.HdrType.TYPE_HLG10)
        .build()

    // Launch the photo picker and let the user choose only videos with
    // transcoding enabled.
    pickMedia.launch(PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.VideoOnly)
        .setMediaCapabilitiesForTranscoding(mediaCapabilities)
        .build())
}

Transkodowanie przez selektor zdjęć zależy od możliwości aplikacji w zakresie multimediów i wybranego filmu. Jeśli transkodowanie zostanie przeprowadzone, zwracany jest identyfikator URI transkodowanego filmu.

Ważne uwagi dotyczące transkodowania HDR

  • Wydajność i miejsce na dane: transkodowanie wymaga czasu i tworzy nowy plik, który zajmuje miejsce na dane.
  • Limit długości wideo: aby zapewnić użytkownikom wygodę i uwzględnić ograniczenia dotyczące miejsca na dane, wprowadziliśmy limit długości wideo wynoszący 1 minutę.
  • Zarządzanie plikami w pamięci podręcznej: pliki transkodowane w pamięci podręcznej są okresowo czyszczone podczas konserwacji w stanie bezczynności, aby zapobiec nadmiernemu wykorzystaniu miejsca na dane.
  • Dostępność na urządzeniach: transkodowanie w selektorze zdjęć jest obsługiwane na Androidzie 13 (poziom interfejsu API 33) i nowszych wersjach.
  • Integracja aktywności AndroidX: upewnij się, że używasz wersji 1.11.0-alpha01 lub nowszej wersji alfa/beta/RC/stabilnej biblioteki aktywności AndroidX, ponieważ zawiera ona niezbędny interfejs API setMediaCapabilitiesForTranscoding.