الفواصل الإعلانية
تتيح حزمة تطوير البرامج (SDK) لمرسِل Android استخدام الفواصل الإعلانية والإعلانات المصاحبة ضمن بث وسائط معيّن.
يمكنك الاطّلاع على نظرة عامة على الفواصل الإعلانية في Web Receiver لمزيد من المعلومات حول طريقة عمل الفواصل الإعلانية.
على الرغم من إمكانية تحديد الفواصل على كل من جهاز الإرسال وجهاز الاستقبال، يُنصح بتحديدها على جهاز استقبال الويب وجهاز استقبال Android TV للحفاظ على اتساق السلوك على جميع الأنظمة الأساسية.
على أجهزة Android، حدِّد الفواصل الإعلانية في أمر التحميل باستخدام
AdBreakClipInfo
وAdBreakInfo:
val breakClip1: AdBreakClipInfo = AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build() val breakClip2: AdBreakClipInfo = … val breakClip3: AdBreakClipInfo = … val break1: AdBreakClipInfo = AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build() val mediaInfo: MediaInfo = MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build() val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build() remoteMediaClient.load(mediaLoadRequestData)
AdBreakClipInfo breakClip1 = new AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build(); AdBreakClipInfo breakClip2 = … AdBreakClipInfo breakClip3 = … AdBreakInfo break1 = new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build(); MediaInfo mediaInfo = new MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build(); MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build(); remoteMediaClient.load(mediaLoadRequestData);
إضافة إجراءات مخصّصة
يمكن لتطبيق المُرسِل توسيع
MediaIntentReceiver
للتعامل مع الإجراءات المخصّصة أو إلغاء سلوكه. إذا نفّذت MediaIntentReceiver الخاص بك، عليك إضافته إلى ملف البيان، وضبط اسمه أيضًا في CastMediaOptions. يقدّم هذا المثال إجراءات مخصّصة تلغي تفعيل تشغيل الوسائط عن بُعد والضغط على زر الوسائط وأنواع أخرى من الإجراءات.
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// In your OptionsProvider var mediaOptions = CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name) .build() // Implementation of MyMediaIntentReceiver internal class MyMediaIntentReceiver : MediaIntentReceiver() { override fun onReceiveActionTogglePlayback(currentSession: Session) { } override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) { } override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) { } }
// In your OptionsProvider CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName()) .build(); // Implementation of MyMediaIntentReceiver class MyMediaIntentReceiver extends MediaIntentReceiver { @Override protected void onReceiveActionTogglePlayback(Session currentSession) { } @Override protected void onReceiveActionMediaButton(Session currentSession, Intent intent) { } @Override protected void onReceiveOtherAction(Context context, String action, Intent intent) { } }
إضافة قناة مخصّصة
لكي يتواصل تطبيق المُرسِل مع تطبيق المُستلِم، يحتاج تطبيقك إلى إنشاء قناة مخصّصة. يمكن للمُرسِل استخدام القناة المخصّصة لإرسال رسائل نصية إلى المُستلِم. يتم تحديد كل قناة مخصّصة من خلال مساحة اسم فريدة، ويجب أن تبدأ بالبادئة urn:x-cast:، على سبيل المثال، urn:x-cast:com.example.custom. يمكن أن يكون لديك عدة قنوات مخصّصة،
ولكل منها مساحة اسم فريدة. يمكن لتطبيق الاستقبال أيضًا
إرسال الرسائل وتلقّيها
باستخدام مساحة الاسم نفسها.
يتم تنفيذ القناة المخصّصة باستخدام واجهة
Cast.MessageReceivedCallback:
class HelloWorldChannel : MessageReceivedCallback { val namespace: String get() = "urn:x-cast:com.example.custom" override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) { Log.d(TAG, "onMessageReceived: $message") } }
class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return "urn:x-cast:com.example.custom"; } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); } }
بعد ربط تطبيق المُرسِل بتطبيق المُستلِم، يمكن إنشاء القناة المخصّصة باستخدام الطريقة
setMessageReceivedCallbacks:
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
بعد إنشاء القناة المخصّصة، يمكن للمُرسِل استخدام الطريقة
sendMessage
لإرسال رسائل نصية إلى المُستلِم عبر تلك القناة:
private fun sendMessage(message: String) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.namespace, message) .setResultCallback { status -> if (!status.isSuccess) { Log.e(TAG, "Sending message failed") } } } catch (e: Exception) { Log.e(TAG, "Exception while sending message", e) } } }
private void sendMessage(String message) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message) .setResultCallback( status -> { if (!status.isSuccess()) { Log.e(TAG, "Sending message failed"); } }); } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); } } }
إتاحة التشغيل التلقائي
يُرجى الاطّلاع على قسم واجهات برمجة التطبيقات الخاصة بالتشغيل التلقائي وقائمة المحتوى التالي.
تجاوز اختيار الصور لقطع واجهة المستخدم
ستعرض المكوّنات المختلفة لإطار العمل (أي مربّع حوار Cast ووحدة التحكّم المصغّرة وUIMediaController، إذا تم ضبطها على هذا النحو) صورة غلاف الوسائط التي يتم بثّها حاليًا. عادةً ما يتم تضمين عناوين URL الخاصة بالعمل الفني للصورة في MediaMetadata للوسائط، ولكن قد يكون لتطبيق المُرسِل مصدر بديل لعناوين URL.
تحدّد الفئة
ImagePicker
طريقة لاختيار صورة مناسبة من قائمة الصور
في MediaMetadata، استنادًا إلى استخدام الصورة، على سبيل المثال، صورة مصغّرة
للإشعار أو خلفية بملء الشاشة. يختار التنفيذ التلقائي لـ ImagePicker دائمًا الصورة الأولى، أو يعرض قيمة فارغة في حال عدم توفّر أي صورة في MediaMetadata. يمكن لتطبيقك إنشاء فئة فرعية من ImagePicker وإلغاء طريقة
onPickImage(MediaMetadata, ImageHints)
لتوفير تنفيذ بديل، ثم اختيار تلك الفئة الفرعية
باستخدام طريقة
setImagePicker
الخاصة بـ CastMediaOptions.Builder.
ImageHints
يقدّم تلميحات إلى ImagePicker حول نوع وحجم الصورة التي سيتم اختيارها للعرض في واجهة المستخدم.
تخصيص مربّعات حوار Cast
إدارة مراحل نشاط الجلسة
SessionManager
هو المكان المركزي لإدارة مراحل الجلسة. يستمع SessionManager إلى تغييرات حالة اختيار المسار في Android
MediaRouter
لبدء الجلسات واستئنافها وإنهائها. عند اختيار مسار، سينشئ SessionManager عنصر
Session
ويحاول بدءه أو استئنافه. عند إلغاء اختيار مسار،
سينهي تطبيق "SessionManager" الجلسة الحالية.
لذلك، لضمان إدارة SessionManager لدورات حياة الجلسات بشكل صحيح، عليك
التأكّد مما يلي:
- في مربّع حوار اختيار المسار،
استدعِ
MediaRouter.selectRoute(MediaRouter.RouteInfo)عندما يختار المستخدم جهازًا. - في مربّع حوار وحدة التحكّم في المسار (سواء في حالة
الاتصال أو
حالة
البث)،
يمكنك استدعاء
MediaRouter.unselect(int)عندما يوقف المستخدم البث.
بناءً على طريقة إنشاء مربّعات حوار Cast، قد تحتاج إلى تنفيذ إجراءات إضافية:
- إذا أنشأت مربّعات حوار Cast باستخدام
MediaRouteChooserDialogوMediaRouteControllerDialog، سيتم تعديل اختيار المسار فيMediaRouterتلقائيًا، لذا لا داعي لاتّخاذ أي إجراء. - إذا أعددت زر البث باستخدام
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)أوCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)، يتم إنشاء مربعات الحوار باستخدامMediaRouteChooserDialogوMediaRouteControllerDialog، لذا لا داعي لاتخاذ أي إجراء. - في الحالات الأخرى، ستنشئ مربّعات حوار مخصّصة للبث، لذا عليك اتّباع التعليمات أعلاه لتعديل حالة اختيار المسار في
MediaRouter.
حالة عدم توفّر أجهزة
إذا أنشأت مربّعات حوار مخصّصة للبث، يجب أن يتعامل MediaRouteChooserDialog المخصّص بشكل صحيح مع حالة عدم العثور على أي أجهزة. يجب أن يحتوي مربّع الحوار على مؤشرات توضّح للمستخدمين متى لا يزال تطبيقك يحاول العثور على الأجهزة ومتى لم تعد محاولة الاكتشاف نشطة.
إذا كنت تستخدم MediaRouteChooserDialog التلقائي، ستتم معالجة حالة عدم توفّر أي أجهزة تلقائيًا.
الخطوات التالية
بهذا نكون قد انتهينا من الميزات التي يمكنك إضافتها إلى تطبيق الإرسال على Android. يمكنك الآن إنشاء تطبيق إرسال لنظام أساسي آخر (iOS أو الويب)، أو إنشاء تطبيق استقبال على الويب.