یک ارائه دهنده رسانه ابری برای اندروید ایجاد کنید

یک ارائه‌دهنده‌ی رسانه‌ی ابری، محتوای رسانه‌ی ابری اضافی را برای انتخابگر عکس اندروید فراهم می‌کند. کاربران می‌توانند عکس‌ها یا ویدیوهای ارائه شده توسط ارائه‌دهنده‌ی رسانه‌ی ابری را انتخاب کنند، زمانی که یک برنامه از ACTION_PICK_IMAGES یا ACTION_GET_CONTENT برای درخواست فایل‌های رسانه‌ای از کاربر استفاده می‌کند. یک ارائه‌دهنده‌ی رسانه‌ی ابری همچنین می‌تواند اطلاعاتی در مورد آلبوم‌ها ارائه دهد که می‌توان آن‌ها را در انتخابگر عکس اندروید مرور کرد.

قبل از اینکه شروع کنی

قبل از شروع به ساخت ارائه دهنده رسانه ابری خود، موارد زیر را در نظر بگیرید.

واجد شرایط بودن

اندروید در حال اجرای یک برنامه آزمایشی است که به برنامه‌های معرفی‌شده توسط تولیدکنندگان اصلی تجهیزات (OEM) اجازه می‌دهد تا به ارائه‌دهندگان رسانه ابری تبدیل شوند. در حال حاضر، فقط برنامه‌های معرفی‌شده توسط تولیدکنندگان اصلی تجهیزات (OEM) واجد شرایط شرکت در این برنامه برای تبدیل شدن به ارائه‌دهنده رسانه ابری برای اندروید هستند . هر تولیدکننده اصلی تجهیزات می‌تواند حداکثر ۳ برنامه را معرفی کند. پس از تأیید، این برنامه‌ها به عنوان ارائه‌دهندگان رسانه ابری در هر دستگاه مبتنی بر GMS اندروید که روی آن نصب شده‌اند، قابل دسترسی خواهند بود.

اندروید فهرستی از تمام ارائه‌دهندگان ابری واجد شرایط را در سمت سرور نگهداری می‌کند. هر تولیدکننده اصلی تجهیزات (OEM) می‌تواند با استفاده از یک پوشش قابل تنظیم، یک ارائه‌دهنده ابری پیش‌فرض را انتخاب کند. برنامه‌های معرفی‌شده باید تمام الزامات فنی را برآورده کرده و تمام آزمون‌های کیفیت را با موفقیت پشت سر بگذارند. برای کسب اطلاعات بیشتر در مورد فرآیند و الزامات برنامه آزمایشی ارائه‌دهنده رسانه ابری تولیدکننده اصلی تجهیزات، فرم درخواست را تکمیل کنید .

تصمیم بگیرید که آیا نیاز به ایجاد یک ارائه دهنده رسانه ابری دارید یا خیر

ارائه‌دهندگان رسانه‌های ابری، برنامه‌ها یا سرویس‌هایی هستند که به عنوان منبع اصلی کاربران برای پشتیبان‌گیری و بازیابی عکس‌ها و ویدیوها از فضای ابری عمل می‌کنند. اگر برنامه شما دارای کتابخانه‌ای از محتوای مفید است، اما معمولاً به عنوان یک راه‌حل ذخیره‌سازی عکس استفاده نمی‌شود، باید به جای آن، ایجاد یک ارائه‌دهنده اسناد را در نظر بگیرید.

یک ارائه دهنده ابر فعال به ازای هر پروفایل

برای هر پروفایل اندروید، حداکثر یک ارائه‌دهنده رسانه ابری فعال می‌تواند در یک زمان وجود داشته باشد. کاربران می‌توانند برنامه ارائه‌دهنده رسانه ابری انتخابی خود را در هر زمان از تنظیمات انتخابگر عکس حذف یا تغییر دهند.

به طور پیش‌فرض، انتخابگر عکس اندروید سعی می‌کند به طور خودکار یک ارائه‌دهنده ابری را انتخاب کند.

  • اگر فقط یک ارائه‌دهنده‌ی فضای ابری واجد شرایط روی دستگاه وجود داشته باشد، آن برنامه به‌طور خودکار به‌عنوان ارائه‌دهنده‌ی فعلی انتخاب خواهد شد.
  • اگر بیش از یک ارائه‌دهنده‌ی فضای ابری واجد شرایط روی دستگاه وجود داشته باشد و یکی از آنها با پیش‌فرض انتخاب‌شده توسط تولیدکننده‌ی اصلی (OEM) مطابقت داشته باشد، برنامه‌ی انتخاب‌شده توسط تولیدکننده‌ی اصلی (OEM) انتخاب خواهد شد.

  • اگر بیش از یک ارائه‌دهنده‌ی فضای ابری واجد شرایط روی دستگاه وجود داشته باشد و هیچ‌کدام از آن‌ها با پیش‌فرض انتخاب‌شده توسط تولیدکننده‌ی اصلی (OEM) مطابقت نداشته باشند، هیچ برنامه‌ای انتخاب نخواهد شد.

ارائه دهنده رسانه ابری خود را بسازید

نمودار زیر توالی رویدادها را قبل و در طول یک جلسه انتخاب عکس بین برنامه اندروید، انتخابگر عکس اندروید، MediaProvider دستگاه محلی و یک CloudMediaProvider نشان می‌دهد.

نمودار توالی که جریان را از انتخابگر عکس تا ارائه‌دهنده رسانه ابری نشان می‌دهد
شکل ۱: نمودار توالی رویدادها در طول یک جلسه انتخاب عکس.
  1. این سیستم، ارائه‌دهنده ابری مورد نظر کاربر را مقداردهی اولیه می‌کند و به صورت دوره‌ای، فراداده‌های رسانه‌ای را در بخش انتخابگر عکس اندروید همگام‌سازی می‌کند.
  2. وقتی یک برنامه اندروید، انتخابگر عکس را اجرا می‌کند، قبل از نمایش شبکه آیتم‌های محلی یا ابری ادغام‌شده به کاربر، انتخابگر عکس یک همگام‌سازی افزایشی حساس به تأخیر را با ارائه‌دهنده ابر انجام می‌دهد تا اطمینان حاصل شود که نتایج تا حد امکان به‌روز هستند. پس از دریافت پاسخ یا زمانی که مهلت تعیین‌شده فرا می‌رسد، شبکه انتخابگر عکس اکنون تمام عکس‌های قابل دسترسی را نمایش می‌دهد و عکس‌هایی را که به‌صورت محلی در دستگاه شما ذخیره شده‌اند با عکس‌هایی که از ابر همگام‌سازی شده‌اند، ترکیب می‌کند.
  3. در حالی که کاربر اسکرول می‌کند، انتخابگر عکس، تصاویر کوچک رسانه را از ارائه‌دهنده رسانه ابری دریافت می‌کند تا در رابط کاربری نمایش دهد.
  4. وقتی کاربر جلسه را کامل می‌کند و نتایج شامل یک آیتم رسانه ابری می‌شود، انتخابگر عکس، توصیف‌گرهای فایل را برای محتوا درخواست می‌کند، یک URI تولید می‌کند و به برنامه فراخوانی‌کننده، دسترسی به فایل را اعطا می‌کند.
  5. اکنون برنامه قادر به باز کردن URI است و به محتوای رسانه فقط دسترسی خواندنی دارد. به طور پیش‌فرض، فراداده‌های حساس حذف می‌شوند. انتخابگر عکس از سیستم فایل FUSE برای هماهنگی تبادل داده‌ها بین برنامه اندروید و ارائه‌دهنده رسانه ابری استفاده می‌کند.

مشکلات رایج

در اینجا چند نکته مهم وجود دارد که باید هنگام بررسی پیاده‌سازی خود در نظر داشته باشید:

جلوگیری از کپی کردن فایل‌ها

از آنجایی که انتخابگر عکس اندروید هیچ راهی برای بررسی وضعیت رسانه ابری ندارد، CloudMediaProvider باید MEDIA_STORE_URI را در ردیف مکان‌نمای هر فایلی که هم در فضای ابری و هم در دستگاه محلی وجود دارد، ارائه دهد، در غیر این صورت کاربر فایل‌های تکراری را در انتخابگر عکس مشاهده خواهد کرد.

بهینه‌سازی اندازه تصاویر برای نمایش پیش‌نمایش

بسیار مهم است که فایل برگردانده شده از onOpenPreview تصویر با وضوح کامل نباشد و به Size درخواستی پایبند باشد. تصویر خیلی بزرگ باعث افزایش زمان بارگذاری در رابط کاربری می‌شود و تصویر خیلی کوچک ممکن است بسته به اندازه صفحه نمایش دستگاه، پیکسل پیکسل یا تار باشد.

جهت گیری صحیح را کنترل کنید

اگر تصاویر بندانگشتی بازگردانده شده در onOpenPreview حاوی داده‌های EXIF ​​خود نباشند، باید در جهت صحیح بازگردانده شوند تا از چرخش نادرست تصاویر بندانگشتی در شبکه پیش‌نمایش جلوگیری شود.

جلوگیری از دسترسی غیرمجاز

قبل از بازگرداندن داده‌ها از ContentProvider به فراخوانی‌کننده، MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION را بررسی کنید. این کار از دسترسی برنامه‌های غیرمجاز به داده‌های ابری جلوگیری می‌کند.

کلاس CloudMediaProvider

کلاس CloudMediaProvider که از android.content.ContentProvider مشتق شده است، شامل متدهایی مانند متدهای نشان داده شده در مثال زیر است:

کاتلین

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
}

جاوا

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);
}

کلاس CloudMediaProviderContract

علاوه بر کلاس پیاده‌سازی اولیه CloudMediaProvider ، انتخابگر عکس اندروید شامل یک کلاس CloudMediaProviderContract نیز می‌شود. این کلاس، قابلیت همکاری بین انتخابگر عکس و ارائه‌دهنده رسانه ابری را مشخص می‌کند و شامل جنبه‌هایی مانند MediaCollectionInfo برای عملیات همگام‌سازی، ستون‌های Cursor پیش‌بینی‌شده و موارد اضافی Bundle .

کاتلین

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"
    }
}

جاوا

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";
}

اطلاعات مربوط به مجموعه رسانه‌ای onGetMedia

متد onGetMediaCollectionInfo() توسط سیستم عامل برای ارزیابی اعتبار آیتم‌های رسانه ابری ذخیره شده و تعیین همگام‌سازی لازم با ارائه دهنده رسانه ابری استفاده می‌شود. با توجه به پتانسیل فراخوانی‌های مکرر توسط سیستم عامل، onGetMediaCollectionInfo() از نظر عملکرد بسیار مهم تلقی می‌شود؛ اجتناب از عملیات طولانی مدت یا عوارض جانبی که می‌توانند بر عملکرد تأثیر منفی بگذارند، بسیار مهم است. سیستم عامل پاسخ‌های قبلی از این متد را ذخیره کرده و آنها را با پاسخ‌های بعدی مقایسه می‌کند تا اقدامات مناسب را تعیین کند.

کاتلین

abstract fun onGetMediaCollectionInfo(extras: Bundle): Bundle

جاوا

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

بسته‌ی MediaCollectionInfo برگردانده شده شامل ثابت‌های زیر است:

onQueryMedia

متد onQueryMedia() برای پر کردن جدول اصلی عکس در photo picker در نماهای مختلف استفاده می‌شود. این فراخوانی‌ها ممکن است حساس به تأخیر باشند و می‌توانند به عنوان بخشی از یک همگام‌سازی پیشگیرانه در پس‌زمینه یا در طول جلسات photo picker زمانی که به حالت همگام‌سازی کامل یا افزایشی نیاز است، فراخوانی شوند. رابط کاربری photo picker به طور نامحدود منتظر پاسخ برای نمایش نتایج نمی‌ماند و ممکن است این درخواست‌ها را برای اهداف رابط کاربری به پایان برساند. مکان‌نمای برگشتی همچنان تلاش می‌کند تا برای جلسات آینده در پایگاه داده photo picker پردازش شود.

این متد یک Cursor برمی‌گرداند که نشان‌دهنده‌ی تمام آیتم‌های رسانه‌ای در مجموعه‌ی رسانه‌ای است که به صورت اختیاری توسط اضافات ارائه شده فیلتر شده و به ترتیب زمانی معکوس MediaColumns#DATE_TAKEN_MILLIS (ابتدا جدیدترین آیتم‌ها) مرتب شده‌اند.

بسته‌ی CloudMediaProviderContract برگردانده شده شامل ثابت‌های زیر است:

ارائه‌دهنده‌ی رسانه‌ی ابری باید CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID به عنوان بخشی از Bundle برگردانده شده تنظیم کند. عدم تنظیم این مورد یک خطا محسوب می‌شود و Cursor برگردانده شده را نامعتبر می‌کند. اگر ارائه‌دهنده‌ی رسانه‌ی ابری هرگونه فیلتری را در extras ارائه شده مدیریت کرده باشد، باید کلید را به ContentResolver#EXTRA_HONORED_ARGS به عنوان بخشی از Cursor#setExtras برگردانده شده اضافه کند.

onQueryDeletedMedia

متد onQueryDeletedMedia() برای اطمینان از حذف صحیح موارد حذف شده در حساب ابری از رابط کاربری انتخابگر عکس استفاده می‌شود. با توجه به حساسیت بالقوه آنها به تأخیر، این فراخوانی‌ها ممکن است به عنوان بخشی از موارد زیر آغاز شوند:

  • همگام‌سازی پیشگیرانه‌ی پس‌زمینه
  • جلسات انتخاب عکس (زمانی که حالت همگام‌سازی کامل یا افزایشی مورد نیاز است)

رابط کاربری انتخابگر عکس، تجربه کاربری واکنش‌گرا را در اولویت قرار می‌دهد و برای مدت نامحدود منتظر پاسخ نمی‌ماند. برای حفظ تعامل روان، ممکن است وقفه‌هایی رخ دهد. هر Cursor برگردانده شده همچنان تلاش می‌کند تا برای جلسات آینده در پایگاه داده انتخابگر عکس پردازش شود.

این متد یک Cursor برمی‌گرداند که تمام آیتم‌های رسانه‌ای حذف‌شده در کل مجموعه رسانه‌ای در نسخه فعلی ارائه‌دهنده را که توسط onGetMediaCollectionInfo() برگردانده شده است، نشان می‌دهد. این آیتم‌ها می‌توانند به صورت اختیاری توسط موارد اضافی فیلتر شوند. ارائه‌دهنده رسانه ابری باید CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID را به عنوان بخشی از Cursor#setExtras برگردانده شده تنظیم کند. عدم تنظیم این مورد خطا محسوب می‌شود و Cursor نامعتبر می‌کند. اگر ارائه‌دهنده هرگونه فیلتری را در موارد اضافی ارائه شده مدیریت کرده باشد، باید کلید را به ContentResolver#EXTRA_HONORED_ARGS اضافه کند.

onQueryAlbums

متد onQueryAlbums() برای دریافت لیستی از آلبوم‌های Cloud که در ارائه‌دهنده‌ی ابری موجود هستند و فراداده‌های مرتبط با آنها استفاده می‌شود. برای جزئیات بیشتر به CloudMediaProviderContract.AlbumColumns مراجعه کنید.

این متد یک Cursor برمی‌گرداند که نشان‌دهنده‌ی تمام آیتم‌های آلبوم در مجموعه‌ی رسانه است که به صورت اختیاری توسط موارد اضافی ارائه شده فیلتر شده و به ترتیب زمانی معکوس AlbumColumns#DATE_TAKEN_MILLIS مرتب شده‌اند، به طوری که جدیدترین موارد ابتدا قرار می‌گیرند. ارائه‌دهنده‌ی رسانه‌ی ابری باید CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID را به عنوان بخشی از Cursor برگردانده شده تنظیم کند. عدم تنظیم این مورد خطا محسوب می‌شود و Cursor برگردانده شده را نامعتبر می‌کند. اگر ارائه‌دهنده هرگونه فیلتری را در موارد اضافی ارائه شده مدیریت کرده باشد، باید کلید را به ContentResolver#EXTRA_HONORED_ARGS به عنوان بخشی از Cursor برگردانده شده اضافه کند.

روی‌اوپن‌مدیا

متد onOpenMedia() باید رسانه با اندازه کامل که توسط mediaId ارائه شده شناسایی شده است را برگرداند. اگر این متد هنگام دانلود محتوا به دستگاه مسدود شود، باید به صورت دوره‌ای CancellationSignal ارائه شده را بررسی کنید تا درخواست‌های رها شده را لغو کنید.

نمایش در باز

متد onOpenPreview() باید یک تصویر بندانگشتی با size ارائه شده برای آیتم mediaId ارائه شده برگرداند. این تصویر بندانگشتی باید در CloudMediaProviderContract.MediaColumns#MIME_TYPE اصلی باشد و انتظار می‌رود وضوح بسیار پایین‌تری نسبت به آیتم برگردانده شده توسط onOpenMedia داشته باشد. اگر این متد هنگام دانلود محتوا به دستگاه مسدود شده باشد، باید به صورت دوره‌ای CancellationSignal ارائه شده را بررسی کنید تا درخواست‌های رها شده را لغو کند.

onCreateCloudMediaSurfaceController

متد onCreateCloudMediaSurfaceController() باید یک CloudMediaSurfaceController که برای رندر کردن پیش‌نمایش آیتم‌های رسانه‌ای استفاده می‌شود را برگرداند، یا اگر رندر کردن پیش‌نمایش پشتیبانی نمی‌شود، null برگرداند.

CloudMediaSurfaceController رندر کردن پیش‌نمایش آیتم‌های رسانه‌ای را در نمونه‌های داده شده از Surface مدیریت می‌کند. متدهای این کلاس به صورت ناهمزمان طراحی شده‌اند و نباید با انجام هیچ عملیات سنگینی مسدود شوند. یک نمونه CloudMediaSurfaceController مسئول رندر کردن چندین آیتم رسانه‌ای مرتبط با چندین surface است.

CloudMediaSurfaceController از لیست زیر از فراخوانی‌های چرخه عمر پشتیبانی می‌کند: