یک ارائهدهنده رسانه ابری محتوای رسانه ابری اضافی را برای انتخابگر عکس Android ارائه میکند. هنگامی که یک برنامه از ACTION_PICK_IMAGES
یا ACTION_GET_CONTENT
برای درخواست فایلهای رسانه از کاربر استفاده میکند، کاربران میتوانند عکسها یا ویدیوهای ارائهشده توسط ارائهدهنده رسانه ابری را انتخاب کنند. یک ارائهدهنده رسانه ابری همچنین میتواند اطلاعاتی درباره آلبومها ارائه دهد که میتوانند در انتخابگر عکس Android مرور شوند.
قبل از شروع
قبل از شروع ساخت ارائه دهنده رسانه ابری خود، موارد زیر را در نظر بگیرید.
واجد شرایط بودن
اندروید در حال اجرای یک برنامه آزمایشی است که به برنامه های نامزد شده OEM اجازه می دهد تا به ارائه دهندگان رسانه ابری تبدیل شوند. در حال حاضر فقط برنامههایی که توسط OEM معرفی شدهاند، واجد شرایط شرکت در این برنامه برای تبدیل شدن به یک ارائهدهنده رسانه ابری برای Android هستند . هر OEM می تواند حداکثر 3 برنامه را نامزد کند. پس از تأیید، این برنامهها بهعنوان ارائهدهندگان رسانههای ابری در هر دستگاه مجهز به اندروید GMS که روی آن نصب شدهاند قابل دسترسی میشوند.
Android یک لیست سمت سرور از همه ارائه دهندگان ابری واجد شرایط دارد. هر OEM می تواند یک ارائه دهنده ابر پیش فرض را با استفاده از یک پوشش قابل تنظیم انتخاب کند. برنامههای معرفیشده باید تمام الزامات فنی را داشته باشند و تمام تستهای کیفیت را پشت سر بگذارند. برای کسب اطلاعات بیشتر در مورد فرآیند و الزامات برنامه آزمایشی ارائه دهنده رسانه ابری OEM، فرم درخواست را تکمیل کنید .
تصمیم بگیرید که آیا نیاز به ایجاد یک ارائه دهنده رسانه ابری دارید یا خیر
ارائهدهندگان رسانههای ابری برنامهها یا سرویسهایی هستند که به عنوان منبع اصلی کاربران برای پشتیبانگیری و بازیابی عکسها و ویدیوها از فضای ابری عمل میکنند. اگر برنامه شما دارای کتابخانه ای از محتوای مفید است، اما معمولاً به عنوان یک راه حل ذخیره عکس استفاده نمی شود، باید به جای آن یک ارائه دهنده سند ایجاد کنید.
یک ارائه دهنده ابر فعال در هر نمایه
برای هر نمایه Android میتواند حداکثر یک ارائهدهنده رسانه ابری فعال در هر زمان وجود داشته باشد. کاربران ممکن است برنامه ارائه دهنده رسانه ابری انتخابی خود را در هر زمان از تنظیمات انتخابگر عکس حذف یا تغییر دهند.
بهطور پیشفرض، انتخابگر عکس Android سعی میکند به صورت خودکار یک ارائهدهنده ابر را انتخاب کند.
- اگر فقط یک ارائه دهنده ابر واجد شرایط در دستگاه وجود داشته باشد، آن برنامه به طور خودکار به عنوان ارائه دهنده فعلی انتخاب می شود.
اگر بیش از یک ارائهدهنده ابر واجد شرایط در دستگاه وجود داشته باشد و یکی از آنها با پیشفرض انتخابشده OEM مطابقت داشته باشد، برنامه انتخابشده توسط OEM انتخاب میشود.
اگر بیش از یک ارائهدهنده ابر واجد شرایط در دستگاه وجود داشته باشد و هیچ یک از آنها با پیشفرض انتخابشده OEM مطابقت نداشته باشد، هیچ برنامهای انتخاب نخواهد شد.
ارائه دهنده رسانه ابری خود را بسازید
نمودار زیر توالی رویدادها را قبل و در طول جلسه انتخاب عکس بین برنامه Android، انتخابگر عکس Android، MediaProvider
دستگاه محلی و یک CloudMediaProvider
نشان میدهد.
- این سیستم ارائهدهنده ابر ترجیحی کاربر را مقداردهی اولیه میکند و بهصورت دورهای ابردادههای رسانهای را در پسزمینه انتخابگر عکس Android همگامسازی میکند.
- هنگامی که یک برنامه Android انتخابگر عکس را راهاندازی میکند، قبل از اینکه یک شبکه مورد محلی یا ابری ادغام شده را به کاربر نشان دهد، انتخابگر عکس یک همگامسازی افزایشی حساس به تأخیر با ارائهدهنده ابر انجام میدهد تا مطمئن شود نتایج تا حد امکان بهروز هستند. پس از دریافت پاسخ، یا پس از اتمام مهلت، شبکه انتخابگر عکس اکنون همه عکسهای قابل دسترس را نمایش میدهد و آنهایی را که به صورت محلی در دستگاه شما ذخیره شدهاند با عکسهایی که از ابر همگامسازی شدهاند ترکیب میکند.
- در حالی که کاربر پیمایش می کند، انتخابگر عکس تصاویر کوچک رسانه را از ارائه دهنده رسانه ابری برای نمایش در رابط کاربری واکشی می کند.
- هنگامی که کاربر جلسه را کامل می کند و نتایج شامل یک آیتم رسانه ابری می شود، انتخابگر عکس توصیف کننده های فایل را برای محتوا درخواست می کند، یک URI ایجاد می کند و به برنامه فراخوانی به فایل دسترسی می دهد.
- این برنامه اکنون قادر است URI را باز کند و به محتوای رسانه دسترسی فقط خواندنی دارد. بهطور پیشفرض، ابردادههای حساس ویرایش میشوند. انتخابگر عکس از سیستم فایل FUSE برای هماهنگی تبادل داده بین برنامه Android و ارائه دهنده رسانه ابری استفاده می کند.
مسائل رایج
در اینجا چند نکته مهم وجود دارد که باید هنگام بررسی پیاده سازی خود در نظر داشته باشید:
از فایل های تکراری خودداری کنید
از آنجایی که انتخابگر عکس Android راهی برای بررسی وضعیت رسانه ابری ندارد، 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
اولیه، انتخابگر عکس Android یک کلاس 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
برگشتی شامل ثابت های زیر است:
-
EXTRA_ALBUM_ID
-
EXTRA_LOOPING_PLAYBACK_ENABLED
-
EXTRA_MEDIA_COLLECTION_ID
-
EXTRA_PAGE_SIZE
-
EXTRA_PAGE_TOKEN
-
EXTRA_PREVIEW_THUMBNAIL
-
EXTRA_SURFACE_CONTROLLER_AUDIO_MUTE_ENABLED
-
EXTRA_SYNC_GENERATION
-
MANAGE_CLOUD_MEDIA_PROVIDERS_PERMISSION
-
PROVIDER_INTERFACE
ارائهدهنده رسانه ابری باید CloudMediaProviderContract#EXTRA_MEDIA_COLLECTION_ID
را به عنوان بخشی از Bundle
بازگشتی تنظیم کند. تنظیم نکردن این یک خطا است و Cursor
برگشتی را باطل می کند. اگر ارائهدهنده رسانه ابری فیلترهایی را در موارد اضافی ارائه شده مدیریت میکند، باید کلید را به 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
برگشتی اضافه کند.
در OpenMedia
متد onOpenMedia()
باید رسانه با اندازه کامل شناسایی شده توسط mediaId
ارائه شده را برگرداند. اگر این روش هنگام بارگیری محتوا در دستگاه مسدود می شود، باید به طور دوره ای CancellationSignal
ارائه شده را بررسی کنید تا درخواست های رها شده را لغو کنید.
درOpenPreview
متد onOpenPreview()
باید یک تصویر کوچک با size
ارائه شده برای آیتم mediaId ارائه شده برگرداند. تصویر کوچک باید در CloudMediaProviderContract.MediaColumns#MIME_TYPE
اصلی باشد و انتظار می رود وضوح بسیار کمتری نسبت به موردی که توسط onOpenMedia
برگردانده شده باشد. اگر این روش هنگام بارگیری محتوا در دستگاه مسدود شد، باید به طور دورهای CancellationSignal
ارائه شده را بررسی کنید تا درخواستهای رها شده لغو شود.
onCreateCloudMediaSurfaceController
متد onCreateCloudMediaSurfaceController()
باید یک CloudMediaSurfaceController
را که برای رندر کردن پیشنمایش آیتمهای رسانه استفاده میشود، برگرداند، یا اگر رندر پیشنمایش پشتیبانی نمیشود، null
.
CloudMediaSurfaceController
پیشنمایش آیتمهای رسانه را در نمونههای معینی از Surface
مدیریت میکند. متدهای این کلاس ناهمزمان هستند و نباید با انجام عملیات سنگین مسدود شوند. یک نمونه CloudMediaSurfaceController
مسئول ارائه چندین آیتم رسانه مرتبط با سطوح مختلف است.
CloudMediaSurfaceController
از لیست زیر از تماس های چرخه حیات پشتیبانی می کند:
-
onConfigChange
-
onDestroy
-
onMediaPause
-
onMediaPlay
-
onMediaSeekTo
-
onPlayerCreate
-
onPlayerRelease
-
onSurfaceChanged
-
onSurfaceCreated
-
onSurfaceDestroyed