Công cụ chọn ảnh

Hộp thoại công cụ chọn ảnh sẽ xuất hiện cùng với các tệp nội dung nghe nhìn trên thiết bị của bạn. Chọn một ảnh để chia sẻ với ứng dụng.
Hình 1. Công cụ chọn ảnh cung cấp một giao diện người dùng trực quan để chia sẻ ảnh với ứng dụng của bạn.

Công cụ chọn ảnh cung cấp một giao diện có thể duyệt xem, hiển thị cho người dùng thư viện nội dung nghe nhìn của họ, được sắp xếp theo trình tự từ mới nhất đến cũ nhất. Như đã đề cập trong lớp học lập trình về các phương pháp hay nhất liên quan đến quyền riêng tư, công cụ chọn ảnh cung cấp cho người dùng một cách tiện lợi, an toàn để chỉ cấp cho ứng dụng quyền truy cập vào các hình ảnh và video đã chọn, thay vì toàn bộ thư viện nội dung nghe nhìn.

Với những người dùng mà thiết bị của họ có nhà cung cấp nội dung nghe nhìn trên đám mây đủ điều kiện, thì họ có thể chọn trong số các ảnh và video được lưu trữ từ xa. Tìm hiểu thêm về các nhà cung cấp nội dung nghe nhìn trên đám mây.

Công cụ này tự động cập nhật, cung cấp chức năng mở rộng cho người dùng ứng dụng theo thời gian mà không cần sửa đổi mã.

Sử dụng hợp đồng Hoạt động Jetpack

Để đơn giản hoá việc tích hợp công cụ chọn ảnh, hãy thêm thư viện androidx.activity phiên bản 1.7.0 trở lên.

Sử dụng các hợp đồng kết quả hoạt động sau đây để khởi động công cụ chọn ảnh:

Nếu công cụ chọn ảnh không hoạt động trên một thiết bị, thì thư viện sẽ tự động gọi thao tác theo ý định ACTION_OPEN_DOCUMENT. Ý định này được hỗ trợ trên các thiết bị chạy Android 4.4 (API cấp 19) trở lên. Bạn có thể xác minh xem công cụ chọn ảnh có hoạt động trên một thiết bị nhất định hay không bằng cách gọi isPhotoPickerAvailable().

Chọn một mục nội dung nghe nhìn

Để chọn một mục nội dung nghe nhìn, hãy sử dụng hợp đồng kết quả hoạt động của PickVisualMedia, như trong đoạn mã sau:

Số lượt xem

// 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)))

Thành phần hiển thị

// 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());

Compose

// 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)))

Chọn nhiều mục nội dung nghe nhìn

Để chọn nhiều mục nội dung nghe nhìn, hãy đặt số lượng tối đa tệp nội dung nghe nhìn có thể chọn như trong đoạn mã sau.

Số lượt xem

// 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))

Thành phần hiển thị

// 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());

Compose

// 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))

Nền tảng này giới hạn số lượng tệp tối đa mà bạn có thể yêu cầu người dùng chọn trong công cụ chọn ảnh. Để xem giới hạn này, hãy gọi getPickImagesMaxLimit(). Trên những thiết bị không hỗ trợ công cụ chọn ảnh, giới hạn này sẽ bị bỏ qua.

Thiết bị được hỗ trợ

Công cụ chọn ảnh có sẵn trên thiết bị đáp ứng các tiêu chí sau:

Thiết bị cũ chạy phiên bản Android từ 4.4 (API cấp 19) đến Android 10 (API cấp 29) cũng như thiết bị Android Go chạy Android 11 hoặc 12 có hỗ trợ Dịch vụ Google Play, đều có thể cài đặt công cụ chọn ảnh được điều chỉnh cho phiên bản cũ. Để tự động cài đặt mô-đun công cụ chọn ảnh được điều chỉnh cho phiên bản cũ thông qua Dịch vụ Google Play, hãy thêm mục sau đây vào thẻ <application> trong tệp kê khai của ứng dụng:

<!-- 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>

Duy trì quyền truy cập vào tệp nội dung nghe nhìn

Theo mặc định, hệ thống sẽ cấp cho ứng dụng của bạn quyền truy cập vào các tệp nội dung nghe nhìn cho đến khi thiết bị khởi động lại hoặc ứng dụng ngừng hoạt động. Nếu ứng dụng của bạn thực hiện các tác vụ chạy trong thời gian dài, chẳng hạn như tải một tệp lớn lên trong nền, thì có thể bạn cần có quyền truy cập này lâu hơn. Để làm việc này, hãy gọi phương thức 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);

Xử lý video HDR bằng tính năng chuyển mã

Android 13 (API 33) ra mắt khả năng quay video có Dải động cao (HDR). Mặc dù HDR mang đến trải nghiệm hình ảnh sống động hơn, nhưng một số ứng dụng cũ có thể không được trang bị để xử lý các định dạng mới này, dẫn đến các vấn đề như màu sắc hiển thị không tự nhiên trong quá trình phát (chẳng hạn như khuôn mặt có màu xanh lục). Để giải quyết vấn đề về khả năng tương thích này, bộ chọn ảnh cung cấp một tính năng chuyển mã có thể tự động chuyển đổi video HDR sang định dạng Dải màu động tiêu chuẩn (SDR) trước khi cung cấp cho ứng dụng yêu cầu.

Mục tiêu chính của việc chuyển mã bộ chọn ảnh là đảm bảo trải nghiệm nhất quán và chính xác về mặt hình ảnh đối với nội dung nghe nhìn trên nhiều ứng dụng hơn, ngay cả những ứng dụng chưa có chế độ hỗ trợ HDR rõ ràng. Bằng cách chuyển mã video HDR sang SDR, bộ chọn ảnh hướng đến việc cải thiện khả năng tương thích của ứng dụng và mang lại trải nghiệm liền mạch cho người dùng.

Cách hoạt động của tính năng chuyển mã của bộ chọn ảnh

Theo mặc định, tính năng chuyển mã HDR của công cụ chọn ảnh không được bật. Để bật tính năng này, ứng dụng của bạn cần khai báo rõ ràng các chức năng xử lý định dạng nội dung nghe nhìn khi khởi chạy bộ chọn ảnh.

Ứng dụng của bạn cung cấp các chức năng xử lý nội dung nghe nhìn cho công cụ chọn ảnh. Việc này được thực hiện khi chạy công cụ chọn ảnh bằng thư viện Hoạt động AndroidX bằng cách thêm mediaCapabilities vào PickVisualMediaRequest.Builder. Một API mới, setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?), đã được thêm vào PickVisualMediaRequest.Builder để hỗ trợ việc này.

Bạn có thể kiểm soát hành vi chuyển mã HDR bằng cách sử dụng lớp MediaCapabilities. Cung cấp một đối tượng MediaCapabilities chỉ định chính xác những loại HDR mà ứng dụng của bạn hỗ trợ (ví dụ: TYPE_HLG10, TYPE_HDR10, TYPE_HDR10_PLUS, TYPE_DOLBY_VISION).

Để tắt hoàn toàn tính năng chuyển mã, hãy truyền null cho MediaCapabilities. Mọi loại HDR không được liệt kê rõ ràng trong các chức năng mà bạn cung cấp sẽ được coi là không được hỗ trợ. API này được hỗ trợ trên Android 13 (API cấp 33) trở lên và được chú thích bằng @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())
}

Việc chuyển mã bằng công cụ chọn ảnh dựa trên cả khả năng đa phương tiện của ứng dụng và video đã chọn. Một URI đến video được chuyển mã sẽ được trả về nếu quá trình chuyển mã được thực hiện.

Những điểm cần lưu ý quan trọng khi chuyển mã HDR

  • Hiệu suất và bộ nhớ: Quá trình chuyển mã mất thời gian xử lý và tạo một tệp mới, do đó sẽ tiêu tốn bộ nhớ.
  • Giới hạn về thời lượng video: Để cân bằng trải nghiệm người dùng và các hạn chế về bộ nhớ, chúng tôi giới hạn thời lượng video ở mức 1 phút.
  • Quản lý tệp được lưu vào bộ nhớ đệm: Các tệp được chuyển mã và lưu vào bộ nhớ đệm sẽ được xoá định kỳ trong quá trình bảo trì khi thiết bị ở trạng thái không hoạt động để tránh sử dụng quá nhiều bộ nhớ.
  • Phạm vi hỗ trợ trên thiết bị: Tính năng chuyển mã của công cụ chọn ảnh được hỗ trợ trên Android 13 (API cấp 33) trở lên.
  • Tích hợp hoạt động AndroidX: Đảm bảo bạn đang sử dụng thư viện AndroidX Activity phiên bản 1.11.0-alpha01 hoặc phiên bản alpha/beta/RC/ổn định sau này, vì phiên bản này có chứa API setMediaCapabilitiesForTranscoding cần thiết.