الفواصل الإعلانية
توفِّر حزمة تطوير البرامج (SDK) لأداة iOS Sender دعم الفواصل الإعلانية والإعلانات المصاحبة ضمن بث وسائط معيّن.
يمكنك الاطّلاع على نظرة عامة على الفواصل الإعلانية في أجهزة استقبال الويب لمزيد من المعلومات حول طريقة عمل الفواصل الإعلانية.
يمكن تحديد الفواصل على كلّ من المرسِل والمستلِم، ولكن يُنصح بتحديدها في جهاز الاستقبال على الويب وجهاز استقبال Android TV للحفاظ على سلوك متّسق على مختلف الأنظمة الأساسية.
على نظام التشغيل iOS، حدِّد الفواصل الإعلانية في أمر تحميل باستخدام السمة
GCKAdBreakClipInfo
وGCKAdBreakInfo
:
let breakClip1Builder = GCKAdBreakClipInfoBuilder(adBreakClipID: "bc0") breakClip1Builder.title = "Clip title" if let posterUrl = URL(string: "https://www.some.url") { breakClip1Builder.posterURL = posterUrl } breakClip1Builder.duration = 60 breakClip1Builder.whenSkippable = 5 // Set this field so that the ad is skippable let breakClip1 = breakClip1Builder.build() let breakClip2 = ... let breakClip3 = ... let break1 = GCKAdBreakInfoBuilder(adBreakID: "b0", adBreakClipIds: ["bc0", "bc1", "bc2"]).build() let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "entity") ... mediaInfoBuilder.adBreaks = [break1] mediaInfoBuilder.adBreakClips = [breakClip1, breakClip2, breakClip3] ... mediaInformation = mediaInfoBuilder.build() let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder() mediaLoadRequestDataBuilder.mediaInformation = mediaInformation sessionManager.currentSession?.remoteMediaClient?.loadMedia(with: mediaLoadRequestDataBuilder.build())
GCKAdBreakClipInfoBuilder *breakClipInfoBuilder = [[GCKAdBreakClipInfoBuilder alloc] initWithAdBreakClipID:@"bc0"]; breakClipInfoBuilder.title = @"Clip title"; breakClipInfoBuilder.posterURL = [[NSURL alloc] initWithString:@"https://www.some.url"]; breakClipInfoBuilder.duration = 60; breakClipInfoBuilder.whenSkippable = 5; GCKAdBreakClipInfo *breakClip1 = breakClipInfoBuilder.build; GCKAdBreakClipInfo *breakClip2 = ... GCKAdBreakClipInfo *breakClip3 = ... GCKAdBreakInfo *break1 = [[GCKAdBreakInfoBuilder alloc] initWithAdBreakID:@"b0" adBreakClipIds:@[@"bc0", @"bc1", @"bc2"]].build; GCKMediaInformationBuilder *mediaInfoBuilder = [[GCKMediaInformationBuilder alloc] initWithEntity:@"entity"]; ... mediaInfoBuilder.adBreaks = @[break1]; mediaInfoBuilder.adBreakClips = @[breakClip1, breakClip2, breakClip3]; ... self.mediaInformation = [mediaInfoBuilder build]; GCKMediaLoadRequestDataBuilder *mediaLoadRequestDataBuilder = [[GCKMediaLoadRequestDataBuilder alloc] init]; mediaLoadRequestDataBuilder.mediaInformation = self.mediaInformation; // Send a load request to the remote media client. GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMediaWithLoadRequestData:[mediaLoadRequestDataBuilder build]];
معدل التشغيل المتغير
يمكن لتطبيقك عرض معدل تشغيل ملف الوسائط الحالي وتغييره.
يمكنك ضبط السعر باستخدام -[setPlaybackRate:]
أو
-[setPlaybackRate:customData:]
من
GCKRemoteMediaClient
،
والوصول إلى GCKUIPlaybackRateController
باستخدام playbackRateController
من
GCKUIMediaController
،
وعرض معدل التشغيل الحالي باستخدام playbackRate
من
GCKUIPlaybackRateController
.
نموذج التعليمات البرمجية
يستخدم الملفان التاليان السمة GCKUIPlaybackRateController
التي تتحكّم في معدّل التشغيل باستخدام
عنصر تحكّم مقسّم يحتوي على أزرار "عادية" و"نصف سرعة"
و"سرعة مزدوجة":
import GoogleCast /** * An implementation of GCKUIPlaybackRateController that controls playback rate * using a segmented control that has "normal", "half speed", and "double speed" * buttons. */ class SegmentedButtonPlaybackRateController: GCKUIPlaybackRateController { static let kSegmentNormal = 0; static let kSegmentHalfSpeed = 1; static let kSegmentDoubleSpeed = 2; var segmentedControl: UISegmentedControl! override var playbackRate: Float { didSet { var buttonIndex = 0 // Map the playback rate to one of our three supported speeds. if playbackRate == 1.0 { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentNormal } else if playbackRate < 1.0 { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentHalfSpeed } else { buttonIndex = SegmentedButtonPlaybackRateController.kSegmentDoubleSpeed } segmentedControl?.selectedSegmentIndex = buttonIndex } } override var inputEnabled: Bool { didSet { segmentedControl?.isEnabled = inputEnabled } } /** * Designated initializer. * * @param segmentedControl The segmented control for changing/displaying the * playback rate. */ convenience init(_ segmentedControl: UISegmentedControl) { self.init() self.segmentedControl = segmentedControl; segmentedControl.addTarget(self, action: #selector(segmentedControlTapped(sender:)), for: UIControl.Event.valueChanged) } @objc func segmentedControlTapped(sender: UISegmentedControl) { var playbackRate: Float = 1.0 switch segmentedControl?.selectedSegmentIndex { case SegmentedButtonPlaybackRateController.kSegmentHalfSpeed: playbackRate = 0.5; case SegmentedButtonPlaybackRateController.kSegmentDoubleSpeed: playbackRate = 2.0; case SegmentedButtonPlaybackRateController.kSegmentNormal: fallthrough default: playbackRate = 1.0; } self.playbackRate = playbackRate } }
SegmentedButtonPlaybackRateController.h
#import <GoogleCast/GoogleCast.h> #import <UIKit/UIKit.h> /** * An implementation of GCKUIPlaybackRateController that controls playback rate * using a segmented control that has "normal", "half speed", and "double speed" * buttons. */ @interface SegmentedButtonPlaybackRateController : GCKUIPlaybackRateController /** * Designated initializer. * * @param segmentedControl The segmented control for changing/displaying the * playback rate. */ - (instancetype)initWithSegmentedControl:(UISegmentedControl *)segmentedControl; @end
SegmentedButtonPlaybackRateController.m
#import "SegmentedButtonPlaybackRateController.h" @interface SegmentedButtonPlaybackRateController () { UISegmentedControl *_segmentedControl; } @end static const NSInteger kSegmentNormal = 0; static const NSInteger kSegmentHalfSpeed = 1; static const NSInteger kSegmentDoubleSpeed = 2; @implementation SegmentedButtonPlaybackRateController - (instancetype)initWithSegmentedControl:(UISegmentedControl *)segmentedControl { if (self = [super init]) { _segmentedControl = segmentedControl; [_segmentedControl addTarget:self action:@selector(segmentedControlTapped:) forControlEvents:UIControlEventValueChanged]; } return self; } - (void)setPlaybackRate:(float)playbackRate { [super setPlaybackRate:playbackRate]; NSInteger buttonIndex = 0; // Map the playback rate to one of our three supported speeds. if (playbackRate == 1.0) { buttonIndex = kSegmentNormal; } else if (playbackRate < 1.0) { buttonIndex = kSegmentHalfSpeed; } else { buttonIndex = kSegmentDoubleSpeed; } _segmentedControl.selectedSegmentIndex = buttonIndex; } - (void)setInputEnabled:(BOOL)inputEnabled { _segmentedControl.enabled = inputEnabled; [super setInputEnabled:inputEnabled]; } - (void)segmentedControlTapped:(id)sender { float playbackRate; switch (_segmentedControl.selectedSegmentIndex) { case kSegmentHalfSpeed: playbackRate = 0.5; break; case kSegmentDoubleSpeed: playbackRate = 2.0; break; case kSegmentNormal: default: playbackRate = 1.0; break; } self.playbackRate = playbackRate; } @end
إضافة قناة مخصّصة
يوفر إطار عمل Google Cast طريقتين لإنشاء قناة لإرسال رسائل مخصصة إلى مستقبل الويب:
- الهدف من السمة
GCKCastChannel
هو أن يتم تصنيفها ضمن فئة فرعية لتنفيذ قنوات غير بسيطة لها حالة مرتبطة. - يتم توفير
GCKGenericChannel
كبديل للتصنيف الفرعي، فهي تمرِّر الرسائل المستلَمة إلى المفوَّض حتى تتم معالجتها في مكان آخر.
إليك مثال على استخدام GCKCastChannel
:
class HGCTextChannel: GCKCastChannel { override func didReceiveTextMessage(_ message: String) { print("received message: \(message)") } }
HGCTextChannel.h
#import <GoogleCast/GCKCastChannel.h> @interface HGCTextChannel : GCKCastChannel @end
HGCTextChannel.m
#import "HGCTextChannel.h" @implementation HGCTextChannel - (void)didReceiveTextMessage:(NSString*)message { NSLog(@"received message: %@", message); } @end
يمكن تسجيل أي قناة في أي وقت. وإذا لم تكن الجلسة في حالة متّصلة حاليًا، سيتمّ ربط القناة تلقائيًا عندما تكون الجلسة نفسها مرتبطة، شرط أن تكون مساحة اسم القناة مضمّنة في قائمة البيانات الوصفية لمساحات الاسم المتوافقة الخاصة بتطبيق WebRecipient.
يتم تحديد كل قناة مخصّصة بمساحة اسم فريدة ويجب أن تبدأ بالبادئة urn:x-cast:
، على سبيل المثال urn:x-cast:com.example.custom
. من الممكن أن يكون لديك عدّة قنوات مخصّصة، لكل منها مساحة اسم فريدة. ويمكن أيضًا لتطبيق WebRecipients إرسال الرسائل واستلامها باستخدام مساحة الاسم نفسها.
var error: GCKError? let textChannel = HGCTextChannel.init(namespace: "urn:x-cast:com.google.cast.sample.helloworld") sessionManager.currentCastSession?.add(textChannel) textChannel.sendTextMessage("Hello World", error: &error) if error != nil { print("Error sending text message \(error.debugDescription)") }
NSError *error; HGCTextChannel *textChannel = [[HGCTextChannel alloc] initWithNamespace:@"urn:x-cast:com.google.cast.sample.helloworld"]; [sessionManager.currentCastSession addChannel:textChannel]; [textChannel sendTextMessage:@"Hello World" error:&error]; if (error != nil) { NSLog(@"Error sending text message: %@", error); }
لتوفير المنطق المطلوب تنفيذه عندما تصبح قناة معيّنة
مرتبطة أو غير متصلة، عليك إلغاء الطريقتَين -[didConnect]
و-[didDisconnect]
في حال استخدام GCKCastChannel
، أو
توفير عمليات تنفيذ لطريقتَي -[castChannelDidConnect:]
و-[castChannelDidDisconnect:]
GCKGenericChannelDelegate
في حال استخدام GCKGenericChannel
.
إتاحة التشغيل التلقائي
يُرجى الاطّلاع على واجهات برمجة تطبيقات التشغيل التلقائي والإضافة إلى قائمة المحتوى التالي.
إلغاء اختيار الصور والتخزين المؤقت
ستعرِض المكوّنات المختلفة لإطار العمل (لا سيّما مربّع حوار Google Cast ووحدة التحكّم الصغيرة
ووحدة التحكّم الموسّعة وGCKUIMediaController
في حال ضبطها) العمل الفني للوسائط التي يتم بثها حاليًا. يتم عادةً تضمين عناوين URL الخاصة بالصورة الفنية في GCKMediaMetadata
للوسائط، ولكن قد يكون لدى تطبيق المرسِل مصدر بديل لعناوين URL.
يحدد
بروتوكول GCKUIImagePicker
وسائل لاختيار صورة مناسبة لاستخدام معين
والحجم المطلوب. وهي تستخدم طريقة واحدة، -[getImageWithHints:fromMetadata:]
،
تتعامل مع كائن
GCKUIImageHints
وكائن
GCKMediaMetadata
كمعلَمتَين، وتعرض كائن
GCKImage
كنتيجة. يوفّر إطار العمل طريقة تنفيذ تلقائية لـ
GCKUIImagePicker
الذي يحدد دائمًا الصورة الأولى في قائمة الصور في عنصر GCKMediaMetadata
، ولكن يمكن للتطبيق توفير طريقة تنفيذ بديلة من خلال ضبط السمة imagePicker
في
GCKCastContext
.
يحدّد بروتوكول
GCKUIImageCache
أيضًا طريقة التخزين المؤقت للصور التي يتم تنزيلها
من خلال إطار العمل باستخدام HTTPS. يوفّر إطار العمل طريقة تنفيذ تلقائية لـ
GCKUIImageCache
الذي يخزِّن ملفات الصور التي يتم تنزيلها في دليل ذاكرة التخزين المؤقت
للتطبيق، إلا أنّ التطبيق يمكن أن يوفّر طريقة تنفيذ بديلة من خلال ضبط السمة
imageCache
على
GCKCastContext
سينجلتون.
الخطوات التالية
وبذلك تنتهي الميزات التي يمكنك إضافتها إلى تطبيق iOS Sender. يمكنك الآن إنشاء تطبيق مُرسِل لنظام أساسي آخر (Android أو الويب)، أو إنشاء جهاز استقبال الويب.