Tạo nhà cung cấp nội dung nghe nhìn trên đám mây cho Android

Nhà cung cấp nội dung nghe nhìn trên đám mây sẽ cung cấp thêm nội dung nghe nhìn trên đám mây cho công cụ chọn ảnh của Android. Người dùng có thể chọn ảnh hoặc video do nhà cung cấp nội dung nghe nhìn trên đám mây cung cấp khi một ứng dụng sử dụng ACTION_PICK_IMAGES hoặc ACTION_GET_CONTENT để yêu cầu người dùng cung cấp tệp nội dung nghe nhìn. Nhà cung cấp nội dung nghe nhìn trên đám mây cũng có thể cung cấp thông tin về album. Bạn có thể duyệt xem thông tin này trong công cụ chọn ảnh của Android.

Trước khi bắt đầu

Hãy cân nhắc các mục sau trước khi bạn bắt đầu xây dựng nhà cung cấp nội dung nghe nhìn trên đám mây.

Điều kiện sử dụng

Android đang chạy một chương trình thí điểm cho phép các ứng dụng được OEM chỉ định trở thành nhà cung cấp nội dung nghe nhìn trên đám mây. Hiện tại, chỉ những ứng dụng do OEM đề xuất mới đủ điều kiện tham gia chương trình này để trở thành nhà cung cấp nội dung nghe nhìn trên đám mây cho Android. Mỗi OEM có thể chỉ định tối đa 3 ứng dụng. Sau khi được phê duyệt, các ứng dụng này có thể truy cập được dưới dạng nhà cung cấp dịch vụ phương tiện trên đám mây trên mọi thiết bị chạy GMS Android có cài đặt các ứng dụng đó.

Android duy trì một danh sách phía máy chủ gồm tất cả các nhà cung cấp dịch vụ đám mây đủ điều kiện. Mỗi OEM có thể chọn một nhà cung cấp dịch vụ đám mây mặc định bằng cách sử dụng một lớp phủ có thể định cấu hình. Ứng dụng được chỉ định phải đáp ứng tất cả yêu cầu kỹ thuật và vượt qua mọi bài kiểm tra chất lượng. Để tìm hiểu thêm về quy trình và yêu cầu của chương trình thí điểm nhà cung cấp nội dung nghe nhìn trên đám mây của OEM, hãy hoàn tất biểu mẫu yêu cầu.

Quyết định xem bạn có cần tạo một nhà cung cấp nội dung nghe nhìn trên đám mây hay không

Nhà cung cấp nội dung nghe nhìn trên đám mây là các ứng dụng hoặc dịch vụ đóng vai trò là nguồn chính của người dùng để sao lưu và truy xuất ảnh cũng như video từ đám mây. Nếu ứng dụng của bạn có thư viện nội dung hữu ích, nhưng thư viện đó thường không được dùng làm giải pháp lưu trữ ảnh, thì bạn nên cân nhắc tạo trình cung cấp tài liệu.

Một nhà cung cấp dịch vụ đám mây đang hoạt động cho mỗi hồ sơ

Mỗi hồ sơ Android có thể có tối đa một nhà cung cấp dịch vụ nghe nhìn trên đám mây đang hoạt động tại một thời điểm. Người dùng có thể xoá hoặc thay đổi ứng dụng của nhà cung cấp nội dung nghe nhìn trên đám mây mà họ đã chọn bất cứ lúc nào trong phần cài đặt công cụ chọn ảnh.

Theo mặc định, công cụ chọn ảnh của Android sẽ tự động chọn nhà cung cấp dịch vụ đám mây.

  • Nếu chỉ có một nhà cung cấp dịch vụ đám mây đủ điều kiện trên thiết bị, ứng dụng đó sẽ tự động được chọn làm nhà cung cấp hiện tại.
  • Nếu có nhiều nhà cung cấp dịch vụ đám mây đủ điều kiện trên thiết bị và một trong số các nhà cung cấp đó khớp với giá trị mặc định đã chọn của OEM, thì ứng dụng do OEM chọn sẽ được chọn.

  • Nếu có nhiều nhà cung cấp dịch vụ đám mây đủ điều kiện trên thiết bị và không có nhà cung cấp nào trong số đó khớp với giá trị mặc định đã chọn của OEM, thì sẽ không có ứng dụng nào được chọn.

Xây dựng nhà cung cấp nội dung nghe nhìn trên đám mây

Sơ đồ dưới đây minh hoạ trình tự của các sự kiện cả trước và trong phiên lựa chọn ảnh giữa ứng dụng Android, công cụ chọn ảnh của Android, MediaProvider của thiết bị cục bộ và CloudMediaProvider.

Sơ đồ trình tự cho thấy quy trình từ công cụ chọn ảnh đến một nhà cung cấp nội dung nghe nhìn trên đám mây
Hình 1: Sơ đồ trình tự sự kiện trong một phiên lựa chọn ảnh.
  1. Hệ thống sẽ khởi chạy nhà cung cấp dịch vụ đám mây mà người dùng ưu tiên và định kỳ đồng bộ hoá siêu dữ liệu nội dung đa phương tiện vào phần phụ trợ công cụ chọn ảnh của Android.
  2. Khi một ứng dụng Android chạy công cụ chọn ảnh, trước khi hiển thị lưới mục cục bộ hoặc lưới hợp nhất trên đám mây cho người dùng, công cụ chọn ảnh sẽ thực hiện quá trình đồng bộ hoá gia tăng có giới hạn độ trễ với nhà cung cấp dịch vụ đám mây để đảm bảo kết quả mới nhất có thể. Sau khi nhận được phản hồi hoặc khi hết thời hạn, lưới công cụ chọn ảnh sẽ hiển thị tất cả ảnh có thể truy cập, kết hợp các ảnh được lưu trữ trên thiết bị với những ảnh được đồng bộ hoá từ đám mây.
  3. Trong khi người dùng cuộn, công cụ chọn ảnh sẽ tìm nạp hình thu nhỏ nội dung nghe nhìn từ nhà cung cấp nội dung nghe nhìn trên đám mây để hiển thị trong giao diện người dùng.
  4. Khi người dùng hoàn tất phiên và kết quả bao gồm một mục nội dung nghe nhìn trên đám mây, công cụ chọn ảnh sẽ yêu cầu chỉ số mô tả tệp cho nội dung, tạo URI và cấp quyền truy cập vào tệp đó cho ứng dụng gọi.
  5. Ứng dụng hiện có thể mở URI và có quyền chỉ có thể đọc đối với nội dung nghe nhìn. Theo mặc định, siêu dữ liệu nhạy cảm sẽ bị loại bỏ. Công cụ chọn ảnh sử dụng hệ thống tệp FUSE để điều phối hoạt động trao đổi dữ liệu giữa ứng dụng Android và nhà cung cấp nội dung nghe nhìn trên đám mây.

Các vấn đề thường gặp

Dưới đây là một số điểm quan trọng cần cân nhắc khi cân nhắc triển khai:

Tránh các tệp trùng lặp

Công cụ chọn ảnh của Android không có cách nào để kiểm tra trạng thái nội dung nghe nhìn trên đám mây, nên CloudMediaProvider cần cung cấp MEDIA_STORE_URI trong hàng con trỏ của bất kỳ tệp nào tồn tại cả trên đám mây và trên thiết bị cục bộ, nếu không, người dùng sẽ thấy các tệp trùng lặp trong công cụ chọn ảnh.

Tối ưu hoá kích thước hình ảnh để hiển thị bản xem trước

Điều quan trọng là tệp được trả về từ onOpenPreview không phải là hình ảnh có độ phân giải đầy đủ và phải tuân thủ Size đang được yêu cầu. Một hình ảnh quá lớn sẽ làm mất thời gian tải trong giao diện người dùng, và một hình ảnh quá nhỏ có thể bị tạo pixel hoặc bị mờ tuỳ theo kích thước màn hình của thiết bị.

Xử lý đúng hướng

Nếu hình thu nhỏ được trả về trong onOpenPreview không chứa dữ liệu EXIF, thì các hình thu nhỏ đó phải được trả về theo đúng hướng để tránh bị xoay hình thu nhỏ không đúng cách trong lưới xem trước.

Ngăn chặn hành vi truy cập trái phép

Kiểm tra MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION trước khi trả về dữ liệu cho phương thức gọi từ ContentProvider. Điều này sẽ ngăn các ứng dụng trái phép truy cập vào dữ liệu đám mây.

Lớp CloudMediaProvider

Bắt nguồn từ android.content.ContentProvider, lớp CloudMediaProvider bao gồm các phương thức như các phương thức minh hoạ trong ví dụ sau:

Kotlin

abstract class CloudMediaProvider : ContentProvider() {

    @NonNull
    abstract override fun onGetMediaCollectionInfo(@NonNull bundle: Bundle): Bundle

    @NonNull
    override fun onQueryAlbums(@NonNull bundle: Bundle): Cursor = TODO("Implement onQueryAlbums")

    @NonNull
    abstract override fun onQueryDeletedMedia(@NonNull bundle: Bundle): Cursor

    @NonNull
    abstract override fun onQueryMedia(@NonNull bundle: Bundle): Cursor

    @NonNull
    abstract override fun onOpenMedia(
        @NonNull string: String,
        @Nullable bundle: Bundle?,
        @Nullable cancellationSignal: CancellationSignal?
    ): ParcelFileDescriptor

    @NonNull
    abstract override fun onOpenPreview(
        @NonNull string: String,
        @NonNull point: Point,
        @Nullable bundle: Bundle?,
        @Nullable cancellationSignal: CancellationSignal?
    ): AssetFileDescriptor

    @Nullable
    override fun onCreateCloudMediaSurfaceController(
        @NonNull bundle: Bundle,
        @NonNull callback: CloudMediaSurfaceStateChangedCallback
    ): CloudMediaSurfaceController? = null
}

Java

public abstract class CloudMediaProvider extends android.content.ContentProvider {

  @NonNull
  public abstract android.os.Bundle onGetMediaCollectionInfo(@NonNull android.os.Bundle);

  @NonNull
  public android.database.Cursor onQueryAlbums(@NonNull android.os.Bundle);

  @NonNull
  public abstract android.database.Cursor onQueryDeletedMedia(@NonNull android.os.Bundle);

  @NonNull
  public abstract android.database.Cursor onQueryMedia(@NonNull android.os.Bundle);

  @NonNull
  public abstract android.os.ParcelFileDescriptor onOpenMedia(@NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;

  @NonNull
  public abstract android.content.res.AssetFileDescriptor onOpenPreview(@NonNull String, @NonNull android.graphics.Point, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;

  @Nullable
  public android.provider.CloudMediaProvider.CloudMediaSurfaceController onCreateCloudMediaSurfaceController(@NonNull android.os.Bundle, @NonNull android.provider.CloudMediaProvider.CloudMediaSurfaceStateChangedCallback);
}

Lớp CloudMediaProviderContract

Ngoài lớp triển khai CloudMediaProvider chính, công cụ chọn ảnh của Android còn kết hợp một lớp CloudMediaProviderContract. Lớp này trình bày khả năng tương tác giữa công cụ chọn ảnh và trình cung cấp nội dung nghe nhìn trên đám mây, bao gồm các khía cạnh như MediaCollectionInfo cho hoạt động đồng bộ hoá, cột Cursor dự kiến và dữ liệu bổ sung Bundle.

Kotlin

object CloudMediaProviderContract {

    const val EXTRA_ALBUM_ID = "android.provider.extra.ALBUM_ID"
    const val EXTRA_LOOPING_PLAYBACK_ENABLED = "android.provider.extra.LOOPING_PLAYBACK_ENABLED"
    const val EXTRA_MEDIA_COLLECTION_ID = "android.provider.extra.MEDIA_COLLECTION_ID"
    const val EXTRA_PAGE_SIZE = "android.provider.extra.PAGE_SIZE"
    const val EXTRA_PAGE_TOKEN = "android.provider.extra.PAGE_TOKEN"
    const val EXTRA_PREVIEW_THUMBNAIL = "android.provider.extra.PREVIEW_THUMBNAIL"
    const val EXTRA_SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED = "android.provider.extra.SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED"
    const val EXTRA_SYNC_GENERATION = "android.provider.extra.SYNC_GENERATION"
    const val MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION = "com.android.providers.media.permission.MANAGE_CLOUD_MEDIA_PROVIDERS"
    const val PROVIDER_INTERFACE = "android.content.action.CLOUD_MEDIA_PROVIDER"

    object MediaColumns {
        const val DATE_TAKEN_MILLIS = "date_taken_millis"
        const val DURATION_MILLIS = "duration_millis"
        const val HEIGHT = "height"
        const val ID = "id"
        const val IS_FAVORITE = "is_favorite"
        const val MEDIA_STORE_URI = "media_store_uri"
        const val MIME_TYPE = "mime_type"
        const val ORIENTATION = "orientation"
        const val SIZE_BYTES = "size_bytes"
        const val STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension"
        const val STANDARD_MIME_TYPE_EXTENSION_ANIMATED_WEBP = 3 // 0x3
        const val STANDARD_MIME_TYPE_EXTENSION_GIF = 1 // 0x1
        const val STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO = 2 // 0x2
        const val STANDARD_MIME_TYPE_EXTENSION_NONE = 0 // 0x0
        const val SYNC_GENERATION = "sync_generation"
        const val WIDTH = "width"
    }

    object AlbumColumns {
        const val DATE_TAKEN_MILLIS = "date_taken_millis"
        const val DISPLAY_NAME = "display_name"
        const val ID = "id"
        const val MEDIA_COUNT = "album_media_count"
        const val MEDIA_COVER_ID = "album_media_cover_id"
    }

    object MediaCollectionInfo {
        const val ACCOUNT_CONFIGURATION_INTENT = "account_configuration_intent"
        const val ACCOUNT_NAME = "account_name"
        const val LAST_MEDIA_SYNC_GENERATION = "last_media_sync_generation"
        const val MEDIA_COLLECTION_ID = "media_collection_id"
    }
}

Java

public final class CloudMediaProviderContract {

  public static final String EXTRA_ALBUM_ID = "android.provider.extra.ALBUM_ID";
  public static final String EXTRA_LOOPING_PLAYBACK_ENABLED = "android.provider.extra.LOOPING_PLAYBACK_ENABLED";
  public static final String EXTRA_MEDIA_COLLECTION_ID = "android.provider.extra.MEDIA_COLLECTION_ID";
  public static final String EXTRA_PAGE_SIZE = "android.provider.extra.PAGE_SIZE";
  public static final String EXTRA_PAGE_TOKEN = "android.provider.extra.PAGE_TOKEN";
  public static final String EXTRA_PREVIEW_THUMBNAIL = "android.provider.extra.PREVIEW_THUMBNAIL";
  public static final String EXTRA_SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED = "android.provider.extra.SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED";
  public static final String EXTRA_SYNC_GENERATION = "android.provider.extra.SYNC_GENERATION";
  public static final String MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION = "com.android.providers.media.permission.MANAGE_CLOUD_MEDIA_PROVIDERS";
  public static final String PROVIDER_INTERFACE = "android.content.action.CLOUD_MEDIA_PROVIDER";
}

// Columns available for every media item
public static final class CloudMediaProviderContract.MediaColumns {

  public static final String DATE_TAKEN_MILLIS = "date_taken_millis";
  public static final String DURATION_MILLIS = "duration_millis";
  public static final String HEIGHT = "height";
  public static final String ID = "id";
  public static final String IS_FAVORITE = "is_favorite";
  public static final String MEDIA_STORE_URI = "media_store_uri";
  public static final String MIME_TYPE = "mime_type";
  public static final String ORIENTATION = "orientation";
  public static final String SIZE_BYTES = "size_bytes";
  public static final String STANDARD_MIME_TYPE_EXTENSION = "standard_mime_type_extension";
  public static final int STANDARD_MIME_TYPE_EXTENSION_ANIMATED_WEBP = 3; // 0x3
  public static final int STANDARD_MIME_TYPE_EXTENSION_GIF = 1; // 0x1 
  public static final int STANDARD_MIME_TYPE_EXTENSION_MOTION_PHOTO = 2; // 0x2 
  public static final int STANDARD_MIME_TYPE_EXTENSION_NONE = 0; // 0x0 
  public static final String SYNC_GENERATION = "sync_generation";
  public static final String WIDTH = "width";
}

// Columns available for every album item
public static final class CloudMediaProviderContract.AlbumColumns {

  public static final String DATE_TAKEN_MILLIS = "date_taken_millis";
  public static final String DISPLAY_NAME = "display_name";
  public static final String ID = "id";
  public static final String MEDIA_COUNT = "album_media_count";
  public static final String MEDIA_COVER_ID = "album_media_cover_id";
}

// Media Collection metadata that is cached by the OS to compare sync states.
public static final class CloudMediaProviderContract.MediaCollectionInfo {

  public static final String ACCOUNT_CONFIGURATION_INTENT = "account_configuration_intent";
  public static final String ACCOUNT_NAME = "account_name";
  public static final String LAST_MEDIA_SYNC_GENERATION = "last_media_sync_generation";
  public static final String MEDIA_COLLECTION_ID = "media_collection_id";
}

onGetMediaCollectionInfo

Hệ điều hành sử dụng phương thức onGetMediaCollectionInfo() để đánh giá tính hợp lệ của các mục nội dung nghe nhìn trên đám mây được lưu vào bộ nhớ đệm và xác định quá trình đồng bộ hoá cần thiết với nhà cung cấp nội dung nghe nhìn trên đám mây. Do hệ điều hành có thể nhận được các lệnh gọi thường xuyên, onGetMediaCollectionInfo() được coi là yếu tố quan trọng về hiệu suất. Điều quan trọng là cần tránh các hoạt động diễn ra trong thời gian dài hoặc các tác dụng phụ có thể tác động tiêu cực đến hiệu suất. Hệ điều hành lưu các phản hồi trước đó vào bộ nhớ đệm của phương thức này và so sánh với các phản hồi tiếp theo để xác định các thao tác thích hợp.

Kotlin

abstract fun onGetMediaCollectionInfo(extras: Bundle): Bundle

Java

@NonNull
public abstract Bundle onGetMediaCollectionInfo(@NonNull Bundle extras);

Gói MediaCollectionInfo được trả về bao gồm các hằng số sau:

onQueryMedia

Phương thức onQueryMedia() được dùng để điền lưới ảnh chính trong công cụ chọn ảnh trong nhiều chế độ xem. Các lệnh gọi này có thể nhạy cảm về độ trễ và có thể được gọi trong quá trình đồng bộ hoá chủ động ở chế độ nền hoặc trong các phiên hoạt động của công cụ chọn ảnh khi cần có trạng thái đồng bộ hoá đầy đủ hoặc tăng dần. Giao diện người dùng của công cụ chọn ảnh sẽ không chờ phản hồi vô thời hạn để cho thấy kết quả và có thể hết thời gian chờ cho các yêu cầu này vì mục đích giao diện người dùng. Con trỏ được trả về sẽ vẫn cố gắng được xử lý trong cơ sở dữ liệu của công cụ chọn ảnh cho các phiên trong tương lai.

Phương thức này trả về một Cursor đại diện cho tất cả các mục nội dung đa phương tiện trong bộ sưu tập nội dung nghe nhìn được lọc theo lựa chọn bổ sung được cung cấp và sắp xếp theo thứ tự thời gian đảo ngược là MediaColumns#DATE_TAKEN_MILLIS (các mục gần đây nhất được ưu tiên).

Gói CloudMediaProviderContract được trả về bao gồm các hằng số sau:

Nhà cung cấp nội dung nghe nhìn trên đám mây phải đặt CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID trong Bundle được trả về. Nếu không đặt thì đây là một lỗi và sẽ làm mất hiệu lực của Cursor được trả về. Nếu nhà cung cấp nội dung nghe nhìn trên đám mây đã xử lý bất kỳ bộ lọc nào trong các ứng dụng bổ sung được cung cấp, thì nhà cung cấp đó phải thêm khoá vào ContentResolver#EXTRA_HONORED_ARGS như một phần của Cursor#setExtras được trả về.

onQueryXoáMedia

Phương thức onQueryDeletedMedia() dùng để đảm bảo các mục đã xoá trong tài khoản đám mây được xoá đúng cách khỏi giao diện người dùng của công cụ chọn ảnh. Do độ nhạy về độ trễ tiềm ẩn, các lệnh gọi này có thể được bắt đầu như một phần của:

  • Đồng bộ hoá chủ động ở chế độ nền
  • Phiên công cụ chọn ảnh (khi yêu cầu trạng thái đồng bộ hoá đầy đủ hoặc tăng dần)

Giao diện người dùng của công cụ chọn ảnh ưu tiên trải nghiệm người dùng thích ứng và sẽ không chờ phản hồi vô thời hạn. Để duy trì các hoạt động tương tác suôn sẻ, có thể xảy ra thời gian chờ. Mọi Cursor được trả về vẫn sẽ cố gắng được xử lý trong cơ sở dữ liệu của công cụ chọn ảnh cho các phiên trong tương lai.

Phương thức này trả về một Cursor đại diện cho tất cả các mục nội dung nghe nhìn đã xoá trong toàn bộ bộ sưu tập nội dung nghe nhìn trong phiên bản nhà cung cấp hiện tại do onGetMediaCollectionInfo() trả về. Bạn có thể lọc các mục này theo lựa chọn bổ sung. Nhà cung cấp nội dung nghe nhìn trên đám mây phải đặt CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID trong Cursor#setExtras được trả về. Việc không thiết lập đây là một lỗi và làm mất hiệu lực của Cursor. Nếu ứng dụng nhà cung cấp xử lý bất kỳ bộ lọc nào trong các dữ liệu bổ sung được cung cấp, thì ứng dụng phải thêm khoá vào ContentResolver#EXTRA_HONORED_ARGS.

onQueryAlbums

Phương thức onQueryAlbums() được dùng để tìm nạp danh sách album trên đám mây có sẵn trong nhà cung cấp dịch vụ đám mây và siêu dữ liệu liên kết với các album đó. Hãy xem CloudMediaProviderContract.AlbumColumns để biết thêm thông tin chi tiết.

Phương thức này trả về một Cursor đại diện cho tất cả các mục trong album trong bộ sưu tập nội dung nghe nhìn được lọc tuỳ ý theo các thành phần bổ sung được cung cấp và được sắp xếp theo thứ tự thời gian đảo ngược là AlbumColumns#DATE_TAKEN_MILLIS , các mục gần đây nhất được ưu tiên. Nhà cung cấp nội dung nghe nhìn trên đám mây phải đặt CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID trong Cursor được trả về. Nếu không đặt thì đây là một lỗi và sẽ làm mất hiệu lực của Cursor được trả về. Nếu xử lý bất kỳ bộ lọc nào trong các dữ liệu bổ sung được cung cấp, thì trình cung cấp phải thêm khoá vào ContentResolver#EXTRA_HONORED_ARGS như một phần của Cursor được trả về.

onOpenMedia

Phương thức onOpenMedia() sẽ trả về nội dung nghe nhìn ở kích thước đầy đủ được xác định bằng mediaId được cung cấp. Nếu phương thức này chặn trong khi tải nội dung xuống thiết bị, bạn nên định kỳ kiểm tra CancellationSignal được cung cấp để huỷ các yêu cầu bị bỏ qua.

trênOpenPreview

Phương thức onOpenPreview() sẽ trả về hình thu nhỏ của size đã cung cấp cho mục của mediaId đã cung cấp. Hình thu nhỏ phải ở CloudMediaProviderContract.MediaColumns#MIME_TYPE gốc và dự kiến sẽ có độ phân giải thấp hơn nhiều so với mục do onOpenMedia trả về. Nếu phương thức này bị chặn trong khi tải nội dung xuống thiết bị, bạn nên định kỳ kiểm tra CancellationSignal được cung cấp để huỷ các yêu cầu bị bỏ qua.

onCreateCloudMediaSurfaceController

Phương thức onCreateCloudMediaSurfaceController() sẽ trả về một CloudMediaSurfaceController dùng để hiển thị bản xem trước của các mục nội dung đa phương tiện hoặc null nếu tính năng kết xuất bản xem trước không được hỗ trợ.

CloudMediaSurfaceController quản lý việc hiển thị bản xem trước các mục nội dung đa phương tiện trên các thực thể Surface nhất định. Các phương thức của lớp này không đồng bộ và không nên chặn bằng cách thực hiện bất kỳ thao tác nặng nào. Một thực thể CloudMediaSurfaceController duy nhất chịu trách nhiệm kết xuất nhiều mục nội dung đa phương tiện liên kết với nhiều nền tảng.

CloudMediaSurfaceController hỗ trợ danh sách các phương thức gọi lại trong vòng đời sau đây: