অ্যান্ড্রয়েডের জন্য একটি ক্লাউড মিডিয়া প্রদানকারী তৈরি করুন

একটি ক্লাউড মিডিয়া প্রোভাইডার অ্যান্ড্রয়েড ফটো পিকার- এ অতিরিক্ত ক্লাউড মিডিয়া কন্টেন্ট সরবরাহ করে। যখন কোনো অ্যাপ ACTION_PICK_IMAGES বা ACTION_GET_CONTENT ব্যবহার করে ব্যবহারকারীর কাছ থেকে মিডিয়া ফাইল অনুরোধ করে, তখন ব্যবহারকারীরা ক্লাউড মিডিয়া প্রোভাইডারের সরবরাহ করা ফটো বা ভিডিও নির্বাচন করতে পারেন। একটি ক্লাউড মিডিয়া প্রোভাইডার অ্যালবাম সম্পর্কেও তথ্য দিতে পারে, যা অ্যান্ড্রয়েড ফটো পিকার-এ ব্রাউজ করা যায়।

শুরু করার আগে

আপনার ক্লাউড মিডিয়া প্রোভাইডার তৈরি করা শুরু করার আগে নিম্নলিখিত বিষয়গুলো বিবেচনা করুন।

যোগ্যতা

অ্যান্ড্রয়েড একটি পাইলট প্রোগ্রাম চালাচ্ছে যার মাধ্যমে OEM-মনোনীত অ্যাপগুলো ক্লাউড মিডিয়া প্রোভাইডার হতে পারবে। বর্তমানে, শুধুমাত্র OEM দ্বারা মনোনীত অ্যাপগুলোই অ্যান্ড্রয়েডের জন্য ক্লাউড মিডিয়া প্রোভাইডার হওয়ার এই প্রোগ্রামে অংশগ্রহণের যোগ্য । প্রতিটি OEM সর্বোচ্চ ৩টি অ্যাপ মনোনীত করতে পারে। একবার অনুমোদিত হলে, এই অ্যাপগুলো ইনস্টল করা যেকোনো GMS অ্যান্ড্রয়েড-চালিত ডিভাইসে ক্লাউড মিডিয়া প্রোভাইডার হিসেবে ব্যবহারযোগ্য হয়ে ওঠে।

অ্যান্ড্রয়েড সমস্ত যোগ্য ক্লাউড প্রোভাইডারদের একটি সার্ভার-সাইড তালিকা রক্ষণাবেক্ষণ করে। প্রতিটি OEM একটি কনফিগারযোগ্য ওভারলে ব্যবহার করে একটি ডিফল্ট ক্লাউড প্রোভাইডার বেছে নিতে পারে। মনোনীত অ্যাপগুলিকে অবশ্যই সমস্ত প্রযুক্তিগত প্রয়োজনীয়তা পূরণ করতে হবে এবং সমস্ত গুণমান পরীক্ষায় উত্তীর্ণ হতে হবে। OEM ক্লাউড মিডিয়া প্রোভাইডার পাইলট প্রোগ্রামের প্রক্রিয়া এবং প্রয়োজনীয়তা সম্পর্কে আরও জানতে, অনুসন্ধান ফর্মটি পূরণ করুন

আপনার একটি ক্লাউড মিডিয়া প্রোভাইডার তৈরি করার প্রয়োজন আছে কিনা তা স্থির করুন।

ক্লাউড মিডিয়া প্রোভাইডার হলো এমন অ্যাপ বা পরিষেবা যা ক্লাউড থেকে ফটো ও ভিডিও ব্যাকআপ এবং পুনরুদ্ধার করার জন্য ব্যবহারকারীর প্রধান উৎস হিসেবে কাজ করে। যদি আপনার অ্যাপে দরকারি কন্টেন্টের একটি লাইব্রেরি থাকে, কিন্তু এটি সাধারণত ফটো সংরক্ষণের সমাধান হিসেবে ব্যবহৃত না হয়, তবে এর পরিবর্তে আপনার একটি ডকুমেন্ট প্রোভাইডার তৈরি করার কথা ভাবা উচিত।

প্রতি প্রোফাইলে একজন সক্রিয় ক্লাউড প্রদানকারী

প্রতিটি অ্যান্ড্রয়েড প্রোফাইলের জন্য একবারে সর্বাধিক একটি সক্রিয় ক্লাউড মিডিয়া প্রদানকারী থাকতে পারে। ব্যবহারকারীরা ফটো পিকার সেটিংস থেকে যেকোনো সময় তাদের নির্বাচিত ক্লাউড মিডিয়া প্রদানকারী অ্যাপটি সরাতে বা পরিবর্তন করতে পারেন।

ডিফল্টরূপে, অ্যান্ড্রয়েড ফটো পিকার স্বয়ংক্রিয়ভাবে একটি ক্লাউড প্রোভাইডার বেছে নেওয়ার চেষ্টা করবে।

  • ডিভাইসটিতে যদি কেবল একটিই যোগ্য ক্লাউড প্রোভাইডার থাকে, তাহলে সেই অ্যাপটি স্বয়ংক্রিয়ভাবে বর্তমান প্রোভাইডার হিসেবে নির্বাচিত হবে।
  • ডিভাইসটিতে যদি একাধিক উপযুক্ত ক্লাউড প্রোভাইডার থাকে এবং তাদের মধ্যে কোনো একটি OEM দ্বারা নির্বাচিত ডিফল্টের সাথে মিলে যায়, তাহলে OEM দ্বারা নির্বাচিত অ্যাপটিই নির্বাচিত হবে।

  • ডিভাইসটিতে যদি একাধিক উপযুক্ত ক্লাউড প্রোভাইডার থাকে এবং সেগুলোর কোনোটিই OEM দ্বারা নির্বাচিত ডিফল্টের সাথে না মেলে, তাহলে কোনো অ্যাপই নির্বাচিত হবে না।

আপনার ক্লাউড মিডিয়া প্রদানকারী তৈরি করুন

নিম্নলিখিত ডায়াগ্রামটি অ্যান্ড্রয়েড অ্যাপ, অ্যান্ড্রয়েড ফটো পিকার, স্থানীয় ডিভাইসের MediaProvider এবং একটি CloudMediaProvider মধ্যে একটি ফটো নির্বাচন সেশনের আগে ও চলাকালীন ঘটনাক্রম তুলে ধরে।

ফটো পিকার থেকে ক্লাউড মিডিয়া প্রোভাইডার পর্যন্ত প্রবাহ দেখানো ক্রমিক চিত্র
চিত্র ১: ছবি বাছাই পর্ব চলাকালীন ঘটনাক্রম চিত্র।
  1. সিস্টেমটি ব্যবহারকারীর পছন্দের ক্লাউড প্রোভাইডারকে চালু করে এবং নির্দিষ্ট সময় অন্তর মিডিয়া মেটাডেটা অ্যান্ড্রয়েড ফটো পিকার ব্যাকএন্ডে সিঙ্ক করে।
  2. যখন কোনো অ্যান্ড্রয়েড অ্যাপ ফটো পিকার চালু করে, তখন ব্যবহারকারীকে একত্রিত স্থানীয় বা ক্লাউড আইটেমের গ্রিড দেখানোর আগে, ফলাফল যতটা সম্ভব হালনাগাদ রাখা নিশ্চিত করতে ফটো পিকারটি ক্লাউড প্রোভাইডারের সাথে একটি ল্যাটেন্সি-সংবেদনশীল ইনক্রিমেন্টাল সিঙ্ক সম্পন্ন করে। প্রতিক্রিয়া পাওয়ার পর, বা নির্দিষ্ট সময়সীমা শেষ হলে, ফটো পিকার গ্রিডটি এখন আপনার ডিভাইসে স্থানীয়ভাবে সংরক্ষিত এবং ক্লাউড থেকে সিঙ্ক করা ছবিগুলোকে একত্রিত করে সমস্ত অ্যাক্সেসযোগ্য ফটো প্রদর্শন করে।
  3. ব্যবহারকারী যখন স্ক্রোল করেন, তখন ফটো পিকারটি ক্লাউড মিডিয়া প্রোভাইডার থেকে মিডিয়ার থাম্বনেইলগুলো সংগ্রহ করে UI-তে প্রদর্শন করে।
  4. যখন ব্যবহারকারী সেশনটি সম্পন্ন করেন এবং ফলাফলে কোনো ক্লাউড মিডিয়া আইটেম অন্তর্ভুক্ত থাকে, তখন ফটো পিকারটি সেই কন্টেন্টের জন্য ফাইল ডেসক্রিপ্টরের অনুরোধ করে, একটি URI তৈরি করে এবং আহ্বানকারী অ্যাপ্লিকেশনটিকে ফাইলটিতে অ্যাক্সেস প্রদান করে।
  5. অ্যাপটি এখন URI খুলতে সক্ষম এবং মিডিয়া কন্টেন্টগুলোতে এর শুধুমাত্র পঠনযোগ্য (read-only) অ্যাক্সেস রয়েছে। ডিফল্টরূপে, সংবেদনশীল মেটাডেটা গোপন রাখা হয়। ফটো পিকারটি অ্যান্ড্রয়েড অ্যাপ এবং ক্লাউড মিডিয়া প্রোভাইডারের মধ্যে ডেটা আদান-প্রদান সমন্বয় করতে FUSE ফাইল সিস্টেম ব্যবহার করে।

সাধারণ সমস্যা

আপনার বাস্তবায়ন বিবেচনা করার সময় মনে রাখার মতো কিছু গুরুত্বপূর্ণ বিষয় নিচে দেওয়া হলো:

ডুপ্লিকেট ফাইল এড়িয়ে চলুন

যেহেতু অ্যান্ড্রয়েড ফটো পিকারের ক্লাউড মিডিয়ার অবস্থা যাচাই করার কোনো উপায় নেই, তাই ক্লাউড এবং স্থানীয় ডিভাইস উভয় স্থানে বিদ্যমান যেকোনো ফাইলের কার্সার সারিতে CloudMediaProvider কে MEDIA_STORE_URI প্রদান করতে হবে, অন্যথায় ব্যবহারকারী ফটো পিকার-এ ডুপ্লিকেট ফাইল দেখতে পাবেন।

প্রিভিউ প্রদর্শনের জন্য ছবির আকার অপ্টিমাইজ করুন

এটা খুবই গুরুত্বপূর্ণ যে onOpenPreview থেকে প্রাপ্ত ফাইলটি যেন সম্পূর্ণ রেজোলিউশনের ছবি না হয় এবং অনুরোধ করা Size মধ্যেই থাকে। খুব বড় ছবির কারণে UI লোড হতে বেশি সময় লাগবে, এবং খুব ছোট ছবি ডিভাইসের স্ক্রিনের আকারের উপর ভিত্তি করে পিক্সেলযুক্ত বা ঝাপসা হয়ে যেতে পারে।

সঠিক দিকনির্দেশনা পরিচালনা করুন

onOpenPreview তে প্রদর্শিত থাম্বনেইলগুলিতে যদি তাদের EXIF ​​ডেটা না থাকে, তবে প্রিভিউ গ্রিডে থাম্বনেইলগুলির ভুল ঘূর্ণন এড়ানোর জন্য সেগুলিকে সঠিক অভিমুখীকরণে প্রদর্শন করা উচিত।

অননুমোদিত প্রবেশ প্রতিরোধ করুন

ContentProvider থেকে কলারকে ডেটা ফেরত পাঠানোর আগে MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION যাচাই করুন। এটি অননুমোদিত অ্যাপগুলোকে ক্লাউড ডেটা অ্যাক্সেস করা থেকে বিরত রাখবে।

ক্লাউডমিডিয়াপ্রোভাইডার ক্লাস

android.content.ContentProvider থেকে উদ্ভূত, CloudMediaProvider ক্লাসে নিম্নলিখিত উদাহরণে দেখানো পদ্ধতিগুলোর মতো পদ্ধতি অন্তর্ভুক্ত রয়েছে:

কোটলিন

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

onGetMediaCollectionInfo

onGetMediaCollectionInfo() মেথডটি অপারেটিং সিস্টেম তার ক্যাশ করা ক্লাউড মিডিয়া আইটেমগুলোর বৈধতা যাচাই করতে এবং ক্লাউড মিডিয়া প্রোভাইডারের সাথে প্রয়োজনীয় সিনক্রোনাইজেশন নির্ধারণ করতে ব্যবহার করে। অপারেটিং সিস্টেম দ্বারা ঘন ঘন কল করার সম্ভাবনার কারণে, onGetMediaCollectionInfo() মেথডটিকে পারফরম্যান্সের জন্য অত্যন্ত গুরুত্বপূর্ণ বলে মনে করা হয়; দীর্ঘস্থায়ী অপারেশন বা সাইড এফেক্ট, যা পারফরম্যান্সের উপর নেতিবাচক প্রভাব ফেলতে পারে, তা এড়িয়ে চলা অপরিহার্য। অপারেটিং সিস্টেম এই মেথড থেকে প্রাপ্ত পূর্ববর্তী প্রতিক্রিয়াগুলো ক্যাশ করে রাখে এবং উপযুক্ত পদক্ষেপ নির্ধারণের জন্য সেগুলোকে পরবর্তী প্রতিক্রিয়াগুলোর সাথে তুলনা করে।

কোটলিন

abstract fun onGetMediaCollectionInfo(extras: Bundle): Bundle

জাভা

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

ফেরত আসা MediaCollectionInfo বান্ডেলটিতে নিম্নলিখিত ধ্রুবকগুলি অন্তর্ভুক্ত রয়েছে:

onQueryMedia

onQueryMedia() মেথডটি বিভিন্ন ভিউতে ফটো পিকারের প্রধান ফটো গ্রিডটি পূরণ করতে ব্যবহৃত হয়। এই কলগুলো ল্যাটেন্সি-সংবেদনশীল হতে পারে এবং একটি ব্যাকগ্রাউন্ড প্রোঅ্যাকটিভ সিঙ্কের অংশ হিসাবে, অথবা ফটো পিকার সেশন চলাকালীন যখন একটি সম্পূর্ণ বা ইনক্রিমেন্টাল সিঙ্ক অবস্থার প্রয়োজন হয়, তখন এগুলোকে কল করা যেতে পারে। ফটো পিকারের ইউজার ইন্টারফেস ফলাফল দেখানোর জন্য প্রতিক্রিয়ার জন্য অনির্দিষ্টকাল অপেক্ষা করবে না এবং ইউজার ইন্টারফেসের প্রয়োজনে এই অনুরোধগুলোকে টাইম আউট করে দিতে পারে। ফেরত আসা কার্সরটি ভবিষ্যতের সেশনগুলোর জন্য ফটো পিকারের ডেটাবেসে প্রসেস হওয়ার চেষ্টা চালিয়ে যাবে।

এই মেথডটি একটি Cursor রিটার্ন করে যা মিডিয়া কালেকশনের সমস্ত মিডিয়া আইটেমকে উপস্থাপন করে, যা ঐচ্ছিকভাবে প্রদত্ত এক্সট্রা দ্বারা ফিল্টার করা থাকে এবং MediaColumns#DATE_TAKEN_MILLIS অনুসারে বিপরীত কালানুক্রমিক ক্রমে সাজানো থাকে (সবচেয়ে সাম্প্রতিক আইটেমগুলো প্রথমে)।

ফেরত আসা CloudMediaProviderContract বান্ডেলটিতে নিম্নলিখিত ধ্রুবকগুলি অন্তর্ভুক্ত রয়েছে:

ক্লাউড মিডিয়া প্রোভাইডারকে অবশ্যই ফেরত আসা Bundle অংশ হিসেবে CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID সেট করতে হবে। এটি সেট না করা একটি ত্রুটি এবং ফেরত আসা Cursor অবৈধ করে দেয়। যদি ক্লাউড মিডিয়া প্রোভাইডার প্রদত্ত এক্সট্রাগুলিতে কোনো ফিল্টার পরিচালনা করে থাকে, তবে তাকে অবশ্যই ফেরত আসা Cursor#setExtras এর অংশ হিসেবে ContentResolver#EXTRA_HONORED_ARGS এ কী-টি যোগ করতে হবে।

onQueryDeletedMedia

ক্লাউড অ্যাকাউন্ট থেকে মুছে ফেলা আইটেমগুলো ফটো পিকার ইউজার ইন্টারফেস থেকে সঠিকভাবে সরানো হয়েছে কিনা, তা নিশ্চিত করতে onQueryDeletedMedia() মেথডটি ব্যবহৃত হয়। এগুলোর সম্ভাব্য ল্যাটেন্সি সংবেদনশীলতার কারণে, এই কলগুলো নিম্নলিখিত প্রক্রিয়ার অংশ হিসেবে শুরু করা হতে পারে:

  • পটভূমি সক্রিয় সিঙ্ক্রোনাইজেশন
  • ফটো পিকার সেশন (যখন একটি পূর্ণ বা ক্রমবর্ধমান সিঙ্ক অবস্থার প্রয়োজন হয়)

ফটো পিকারের ইউজার ইন্টারফেস একটি রেসপন্সিভ ইউজার এক্সপেরিয়েন্সকে অগ্রাধিকার দেয় এবং কোনো প্রতিক্রিয়ার জন্য অনির্দিষ্টকাল অপেক্ষা করবে না। মসৃণ ইন্টারঅ্যাকশন বজায় রাখার জন্য, টাইমআউট ঘটতে পারে। ফেরত আসা যেকোনো Cursor ভবিষ্যতের সেশনের জন্য ফটো পিকারের ডেটাবেসে প্রসেস করার চেষ্টা করা হবে।

এই মেথডটি একটি Cursor রিটার্ন করে, যা onGetMediaCollectionInfo() দ্বারা প্রাপ্ত বর্তমান প্রোভাইডার ভার্সনের সম্পূর্ণ মিডিয়া কালেকশনের মধ্যে থাকা সমস্ত ডিলিট করা মিডিয়া আইটেমকে প্রতিনিধিত্ব করে। এই আইটেমগুলো ঐচ্ছিকভাবে এক্সট্রা (extras) দ্বারা ফিল্টার করা যেতে পারে। ক্লাউড মিডিয়া প্রোভাইডারকে অবশ্যই রিটার্ন করা Cursor#setExtras এর অংশ হিসেবে CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID সেট করতে হবে। এটি সেট না করা একটি ত্রুটি এবং Cursor অবৈধ করে দেয়। যদি প্রোভাইডার প্রদত্ত এক্সট্রা-তে কোনো ফিল্টার হ্যান্ডেল করে থাকে, তবে তাকে অবশ্যই ContentResolver#EXTRA_HONORED_ARGS এ কী-টি যোগ করতে হবে।

onQueryAlbums

onQueryAlbums() মেথডটি ক্লাউড প্রোভাইডারে উপলব্ধ ক্লাউড অ্যালবাম এবং তাদের সংশ্লিষ্ট মেটাডেটার একটি তালিকা আনতে ব্যবহৃত হয়। অতিরিক্ত বিবরণের জন্য CloudMediaProviderContract.AlbumColumns দেখুন।

এই মেথডটি একটি Cursor রিটার্ন করে যা মিডিয়া কালেকশনের সমস্ত অ্যালবাম আইটেমকে উপস্থাপন করে। এটি ঐচ্ছিকভাবে প্রদত্ত এক্সট্রা দ্বারা ফিল্টার করা থাকে এবং AlbumColumns#DATE_TAKEN_MILLIS অনুসারে বিপরীত কালানুক্রমিক ক্রমে সাজানো থাকে, যেখানে সবচেয়ে সাম্প্রতিক আইটেমগুলো প্রথমে থাকে। ক্লাউড মিডিয়া প্রোভাইডারকে অবশ্যই রিটার্ন করা Cursor অংশ হিসেবে CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID সেট করতে হবে। এটি সেট না করা একটি ত্রুটি এবং রিটার্ন করা Cursor অবৈধ হয়ে যায়। যদি প্রোভাইডার প্রদত্ত এক্সট্রাগুলিতে কোনো ফিল্টার পরিচালনা করে থাকে, তবে তাকে অবশ্যই রিটার্ন করা Cursor অংশ হিসেবে ContentResolver#EXTRA_HONORED_ARGS এ কী-টি যোগ করতে হবে।

ওপেনমিডিয়াতে

onOpenMedia() মেথডটির উচিত প্রদত্ত mediaId দ্বারা চিহ্নিত পূর্ণ আকারের মিডিয়াটি রিটার্ন করা। ডিভাইসে কন্টেন্ট ডাউনলোড করার সময় যদি এই মেথডটি ব্লক হয়ে যায়, তবে পরিত্যক্ত রিকোয়েস্টগুলো বাতিল করার জন্য আপনার উচিত পর্যায়ক্রমে প্রদত্ত CancellationSignal চেক করা।

ওপেন প্রিভিউতে

onOpenPreview() মেথডটি প্রদত্ত mediaId-এর আইটেমটির জন্য প্রদত্ত size একটি থাম্বনেইল রিটার্ন করবে। থাম্বনেইলটি মূল CloudMediaProviderContract.MediaColumns#MIME_TYPE এ থাকবে এবং এর রেজোলিউশন onOpenMedia দ্বারা রিটার্ন করা আইটেমের চেয়ে অনেক কম হবে বলে আশা করা হচ্ছে। ডিভাইসে কন্টেন্ট ডাউনলোড করার সময় যদি এই মেথডটি ব্লক হয়ে যায়, তবে পরিত্যক্ত রিকোয়েস্টগুলো বাতিল করার জন্য আপনার পর্যায়ক্রমে প্রদত্ত CancellationSignal চেক করা উচিত।

onCreateCloudMediaSurfaceController

onCreateCloudMediaSurfaceController() মেথডটির রিটার্ন করা উচিত এমন একটি CloudMediaSurfaceController যা মিডিয়া আইটেমগুলোর প্রিভিউ রেন্ডার করার জন্য ব্যবহৃত হয়, অথবা প্রিভিউ রেন্ডারিং সমর্থিত না হলে null রিটার্ন করা উচিত।

CloudMediaSurfaceController নির্দিষ্ট Surface ইনস্ট্যান্সগুলিতে মিডিয়া আইটেমগুলির প্রিভিউ রেন্ডার করা পরিচালনা করে। এই ক্লাসের মেথডগুলি অ্যাসিঙ্ক্রোনাস হওয়ার জন্য তৈরি, এবং কোনো ভারী অপারেশন সম্পাদনের মাধ্যমে এগুলিকে ব্লক করা উচিত নয়। একটিমাত্র CloudMediaSurfaceController ইনস্ট্যান্স একাধিক সারফেসের সাথে যুক্ত একাধিক মিডিয়া আইটেম রেন্ডার করার জন্য দায়ী থাকে।

CloudMediaSurfaceController এ নিম্নলিখিত লাইফসাইকেল কলব্যাকগুলোর সমর্থন রয়েছে: