Add pod "ConnectSDK"
to your Podfile and run pod install
.
Open the workspace file and run your project.
In case of Broadcast Upload Extension for Screen Mirroring, set the APPLICATION_EXTENSION_API_ONLY value to NO.
platform :ios, '12.0'
def app_pods
pod 'ConnectSDK/Core', :git => 'https://github.com/ConnectSDK/Connect-SDK-iOS.git', :branch => 'master', :submodules => true
end
target 'ScreenMirroring-Sampler' do
use_frameworks!
app_pods
end
target 'ScreenMirroring-Extension-Sampler' do
use_frameworks!
app_pods
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'No'
end
end
end
end
With Connect SDK integrated in the mobile app, it can cast the screen and sound into the TV screen. This allows you to extend the screen of a mobile app to a larger TV screen and share it with your family.
- Screen mirroring: A way to dispay the entire app screen to the TV.
To capture iPhone screen, you need to implement Broadcast Upload Extension using Replay Kit.
Reference
To use screen mirroring, follow these steps.
Search for devices (TVs) connected to your home network. You can set the filter to only search for TVs that support the screen mirroring function. Since the search for TVs takes some time, it should be started as soon as the app is running.
if (_discoveryManager == nil) {
_discoveryManager = [DiscoveryManager sharedManager];
}
NSArray *capabilities = @[ kScreenMirroringControlScreenMirroring ];
CapabilityFilter *filter = [CapabilityFilter filterWithCapabilities:capabilities];
[_discoveryManager setCapabilityFilters:@[filter]];
[_discoveryManager setPairingLevel:DeviceServicePairingLevelOn];
[_discoveryManager registerDeviceService:[WebOSTVService class] withDiscovery:[SSDPDiscoveryProvider class]];
[_discoveryManager startDiscovery];
Select the TV to run the screen mirroring on by using the Picker.
_discoveryManager.devicePicker.delegate = self;
[_discoveryManager.devicePicker showPicker:nil];
Once the user has selected a device, the application needs to store that device identifier to find it. This sample code uses NSUserDefaults
to store its device identifier.
// MARK: DevicePickerDelegate
- (void)devicePicker:(DevicePicker *)picker didSelectDevice:(ConnectableDevice *)device {
NSString *groupId = @"YOUR APP GROUP ID";
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:groupId];
[sharedDefaults setObject:device.address forKey:kConnectableDeviceIpAddressKey];
[sharedDefaults synchronize];
}
Now you can the screen mirroring. Start capturing the screen by creating an RPSystemBroadcastPickerView
.
if (@available(iOS 12.0, *)) {
RPSystemBroadcastPickerView *rpPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:_rpPickerView.bounds];
rpPickerView.preferredExtension = @"YOUR EXTENSION BUNDLE ID";
rpPickerView.showsMicrophoneButton = NO;
UIButton *button = rpPickerView.subviews.firstObject;
button.imageView.tintColor = UIColor.whiteColor;
[_rpPickerView addSubview:rpPickerView];
} else {
/* UNAVAILABLE */
}
After the screen capture starts, you need to search once again with the information of selected TV device stored in the application.
- (instancetype)init {
self = [super init];
_discoveryManager = [DiscoveryManager sharedManager];
NSString *groupId = @"YOUR APP GROUP ID";
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:groupId];
_deviceAddress = [sharedDefaults stringForKey:kConnectableDeviceIpAddressKey];
NSArray *capabilities = @[ kScreenMirroringControlScreenMirroring ];
CapabilityFilter *filter = [CapabilityFilter filterWithCapabilities:capabilities];
[_discoveryManager setCapabilityFilters:@[filter]];
[_discoveryManager setPairingLevel:DeviceServicePairingLevelOn];
[_discoveryManager registerDeviceService:[WebOSTVService class] withDiscovery:[SSDPDiscoveryProvider class]];
[_discoveryManager startDiscovery];
[_discoveryManager setDelegate:self];
return self;
}
If you find your TV again, get a ScreenMirroringControl object to use the screen mirroring API.
And then, you should immediately call the startScreenMirroring
method.
// MARK: DiscoveryManagerDelegate
- (void)discoveryManager:(DiscoveryManager *)manager didFindDevice:(ConnectableDevice *)device {
if ([device.address caseInsensitiveCompare:_deviceAddress] != NSOrderedSame) {
return;
}
_device = device;
_screenMirroringControl = [_device screenMirroringControl];
if (_screenMirroringControl != nil) {
[_screenMirroringControl startScreenMirroring];
[_screenMirroringControl setScreenMirroringDelegate:self];
}
[_discoveryManager stopDiscovery];
}
You can get CMSampleBufferRef and RPSampleBufferType via SampleHandler's processSampleBuffer:withType:
. It must be delivered to the screen mirroring API.
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
// Handle video sample buffer and audio sample buffer for app
if (_screenMirroringControl != nil) {
[_screenMirroringControl pushSampleBuffer:sampleBuffer with:sampleBufferType];
}
}
The following runtime errors might occur while the screen mirroring is running.
- When the network connection is terminated
- When the TV is turned off
- When the screen mirroring is terminated on the TV
- When the mobile device’s notification terminates the screen mirroring
- When other exceptions occurred
For these errors, it is necessary to receive the error in real-time through the delegate and respond appropriately.
// MARK: ScreenMirroringControlDelegate
- (void)screenMirroringDidStart:(BOOL)result {
NSLog(@"screenMirroringDidStart %d", result);
}
- (void)screenMirroringDidStop:(BOOL)result {
NSLog(@"screenMirroringDidStop %d", result);
}
- (void)screenMirroringErrorDidOccur:(ScreenMirroringError)error {
NSLog(@"screenMirroringErrorDidOccur %d", error);
[self finishBroadcastWithError:NULL];
}
When you want to stop mirroring, call stopScreenMirroring
on broadcastFinished
of SampleHandler.
- (void)broadcastFinished {
// User has requested to finish the broadcast.
if (_screenMirroringControl != nil) {
[_screenMirroringControl stopScreenMirroring];
}