I want to provide screen sharing On/Off Feature in iOS Using Tokbox.
I am able to switch to device screen share but after sharing the screen I am not able to switch back to the device Camara.
I have tried with the following code.
-(void)toogleScreen{
if (isSharingEnable == YES) {
isSharingEnable = NO;
NSLog(#"%#",_publisher.description);
_publisher.videoCapture = nil;
[_publisher setVideoType:OTPublisherKitVideoTypeCamera];
_publisher.audioFallbackEnabled = YES;
} else {
isSharingEnable = YES;
[_publisher setVideoType:OTPublisherKitVideoTypeScreen];
_publisher.audioFallbackEnabled = NO;
TBScreenCapture* videoCapture =
[[TBScreenCapture alloc] initWithView:self.view];
[_publisher setVideoCapture:videoCapture];
}
}
It looks like you might not be setting any video capturer when turning off screencapture. This line:
_publisher.videoCapture = nil;
Is needlessly destructive. Try keeping a internal references to the camera and screen capturers, and initialize them outside of the toggleScreen function:
#implementation MyPublisher {
id <OTVideoCapture> _cameraCapture;
id <OTVideoCapture> _screenCapture;
}
Then, change your toggle method to something like:
-(void)toogleScreen{
if (isSharingEnable == YES) {
isSharingEnable = NO;
[_publisher setVideoCapture:_cameraCapture];
[_publisher setVideoType:OTPublisherKitVideoTypeCamera];
_publisher.audioFallbackEnabled = YES;
} else {
isSharingEnable = YES;
[_publisher setVideoCapture:_screenCapture];
[_publisher setVideoType:OTPublisherKitVideoTypeScreen];
_publisher.audioFallbackEnabled = NO;
}
}
Related
It seems that the general MPMediaPicker is not working anymore on ios13 (ipad air 2, iphone SE)
The example 1:1 copied from there is not showing up the media picker
https://developer.apple.com/documentation/mediaplayer/displaying_a_media_picker_from_your_app
Any tips how to get back functionality??
Note 1
When using using the MPMediaPickerController like this
musicPickerView = [[UIView alloc] initWithFrame:fullScreenRect];
musicPickerView.alpha = 0.0f;
musicPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
musicPicker.showsCloudItems = false;
musicPicker.showsItemsWithProtectedAssets = false;
musicPicker.delegate = self;
musicPicker.allowsPickingMultipleItems = false;
musicPicker.prompt = NSLocalizedString(#"Select a song", #"Select a song");
musicPicker.view.frame = musicPickerView.bounds;
[self addChildViewController:musicPicker];
[musicPickerView addSubview:musicPicker.view];
[self.view addSubview:musicPickerView];
[musicPicker didMoveToParentViewController:self];
[self fadeInMusicPicker:true];
The delegate is not invoked at all. No log is shown, only the native alert.
I am getting this native altert
Internal Error
The requested app extension could not be found
[Cancel]
Note 2
It seems to be the issue when the apple music app is not installed on that device. Does anybody know a reliable way to find out if apple music app is installed?
It seems that the Music app from apple has to be installed on that device. Still not 100% reproducible, but with that app installed, I never saw that issue again.
did you set the permission for the Media Library in your info.plist?
NSAppleMusicUsageDescription
From iOS 13 MPMediaPicker required user authorization, unlike the earlier iOS version. So you need to handle the authentication first and then show the picker if user granted the permission. You code will be as follow,
MPMediaLibraryAuthorizationStatus authorizationStatus = MPMediaLibrary.authorizationStatus;
switch (authorizationStatus)
{
case MPMediaLibraryAuthorizationStatusAuthorized:
{
[self showPickerView];
break;
}
case MPMediaLibraryAuthorizationStatusNotDetermined:
{
// Not yet authorized - request it from the system
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus authorizationStatus)
{
if ( authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized )
{
dispatch_async(dispatch_get_main_queue(), ^{
[self showPickerView];
});
}
else
{
PLog(#"The Media Library was not authorized by the user");
}
}];
break;
}
case MPMediaLibraryAuthorizationStatusRestricted:
case MPMediaLibraryAuthorizationStatusDenied:
{
// user has previously denied access. Ask again with our own alert that is similar to the system alert
// then take them to the System Settings so they can turn it on for the app
break;
}
}
-(void)showPickerView
{
musicPickerView = [[UIView alloc] initWithFrame:fullScreenRect];
musicPickerView.alpha = 0.0f;
musicPicker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
musicPicker.showsCloudItems = false;
musicPicker.showsItemsWithProtectedAssets = false;
musicPicker.delegate = self;
musicPicker.allowsPickingMultipleItems = false;
musicPicker.prompt = NSLocalizedString(#"Select a song", #"Select a song");
musicPicker.view.frame = musicPickerView.bounds;
[self addChildViewController:musicPicker];
[musicPickerView addSubview:musicPicker.view];
[self.view addSubview:musicPickerView];
[musicPicker didMoveToParentViewController:self];
[self fadeInMusicPicker:true];
}
I'm creating a VR app using the DJI SDK.
I have two UIViews, fpvPreviewView1 and fpvPreviewView2.
How do I create two instances of the same camera? It currently only displays in a single view.
Here's the relevant code.
DJICamera *camera = [self fetchCamera];
if (camera && camera.delegate == self)
[camera setDelegate:nil];
[self resetVideoPreview];
- (DJICamera*) fetchCamera {
if (![DJISDKManager product]) {
return nil;
}
if ([[DJISDKManager product] isKindOfClass:[DJIAircraft class]]) {
return ((DJIAircraft*)[DJISDKManager product]).camera;
}else if ([[DJISDKManager product] isKindOfClass:[DJIHandheld class]]){
return ((DJIHandheld *)[DJISDKManager product]).camera;
}
return nil;
}
[[VideoPreviewer instance] setView:self.fpvPreviewView1];
[[VideoPreviewer instance] setView:self.fpvPreviewView2];
[[VideoPreviewer instance] setView:self.fpvPreviewView1];
[[VideoPreviewer instance] setView:self.fpvPreviewView2];
Time sensitive. Please help!
Thanks!
What you are currently doing is reset the view of the video previewer singleton every time.
What you want to do is create multiple instances of VideoPreviewer and keep a reference to manage properly the resources. VideoPreviewer is heavy.
Try this instead:
self.firstVP = [[VideoPreviewer alloc] init];
[self.firstVP setView:self.fpvPreviewView1];
self.secondVP = [[VideoPreviewer alloc] init];
[self.secondVP setView:self.fpvPreviewView2];
Hope this helps.
I'm using UIImagePickerController in my applicaiton.
I'm showing the following alert in button action.
My code looks like the following in alertview delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([alertView.title isEqualToString:#"Choose"]) {
if (buttonIndex == 1) { //Camera
[self presentImagePickerControllerWithCamera:YES];
}
else if(buttonIndex == 2) { //Library
[self presentImagePickerControllerWithCamera:NO];
}
}
}
and the content of the method 'presentImagePickerControllerWithCamera' is:
- (void)presentImagePickerControllerWithCamera:(BOOL)isCamera {
CFStringRef mTypes[2] = { kUTTypeImage, kUTTypeMovie };
CFArrayRef mTypesArray = CFArrayCreate(CFAllocatorGetDefault(), (const void**)mTypes, 2, &kCFTypeArrayCallBacks);
imagePickerController.mediaTypes = (__bridge NSArray*)mTypesArray;
imagePickerController.videoMaximumDuration = 60.0f;
CFRelease(mTypesArray);
if (isCamera) { // Showing the camera (Both Camera and video)
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.videoQuality = UIImagePickerControllerQualityTypeMedium;
imagePickerController.allowsEditing = NO;
}
else { // Showing library (Both Pictures and videos)
imagePickerController.allowsEditing = YES;
imagePickerController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
}
[self presentViewController:imagePickerController animated:YES completion:nil];
}
Here i need to limit the video to 1 min when user is selecting video from library, so i wrote
imagePickerController.videoMaximumDuration = 60.0f;
and
imagePickerController.allowsEditing = YES;
it's working fine. But When the user selects a picture from library i don't want editing(the square box on picture).
Is there any way to achieve it?
Any suggestions would be appreciated.
Thanks in advance.
This isn't possible with your current code.
You've assigned both the media types together. That will show you both image& video in to photo gallery. Once UIImagePickerController will show you'll not have access to it, I mean you can't know what user will select (an image or a video) before delegate get call.
So to achieve this with your case, you've to set each media type at once. And based on that media type, have to set allowsEditing property.
I'm trying to take a picture with my iPad app but when I launch the UIImagePickerController, the camera shows the image in the wrong orientation.
Here is the code where I called the UIImagePickerController :
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0 || buttonIndex == 1) {
// Initialization
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsEditing = YES;
self.imgPicker.delegate = self;
// Chosing the source
if (buttonIndex == 0) {
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; // Displayed in the good orientation
}
else {
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imgPicker.showsCameraControls = YES;
}
// Popup pour la photo
self.imgPicker.allowsEditing = YES;
self.imgPicker.contentSizeForViewInPopover = CGSizeMake(1000, 700);
self.photoPopOver.delegate = self;
self.photoPopOver = [[UIPopoverController alloc] initWithContentViewController:self.imgPicker];
[self.photoPopOver presentPopoverFromRect:self.photoBut.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else {
[self cancel];
}
}
Things to know :
- When I set the sourceType to UIImagePickerControllerSourceTypePhotoLibrary, the view is displayed correctly
- When the picture is taken, it's displayed in the good rotation
I don't if it's useful to tell it but in the parent view controller, I have this :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
How can I fix that ? Thanks a lot !
// Solution is here to fix the Orientation of UIImage picked using UIImagePickerViewController or Camera.
Here is an example to fix the orientation issue check out here
a category is defined to fix the orientation issue in IOS. it happens when you take Picture in Portrait mode using "Camera" app in IOS device and then use it in your application via UIImagePickerViewController because default orientation of Camera is Landscape.
It sounds more like you're having issues with the camera preview having the incorrect orientation versus the image captured. Here is some code to fix your problem.
Here is my problem.
Also please not that I am aware of AdWhirl but choose not to use it because I prefer to have control over what is happening with my ads.
Basically I have iAds and AdMob. I start out always with iAds and if the ads have nothing to show I initialize AdMob and start showing it. Then when iAds finally gets something to show I hide Admob ads and destroy the view and display the iAds again.
This seems to work for 1 iteration meaning :
initialize iAds
iAds have no content to show
hide iAds
initialize Admob
Admob displays ads
iAds have received content so we should display it!
hide Admob
release the Admob view object
The problem is.. over time if I leave the app running and iAd fails to load ads a few times (meaning I do a bit of switching which results in creating Admob views) the released Admob view object is not being released and keeps receiving new ads even though it shouldn't.
Here is the code that I run whenever I receive a code 3 from iAds (meaning :The operation couldn’t be completed. Ad inventory unavailable)
-(void) smartInitialize:(UIViewController*) theVC
{
NSLog(#"AMOB :: smartInitialize");
if(!initialized)
{
NSLog(#"AMOB :: PRE initialization");
CGRect appFrame = [UIScreen mainScreen].applicationFrame;
UIView * theView = [[UIView alloc] initWithFrame:appFrame];
theView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
theViewController = theVC;
//[theViewController retain];
self.view = theView;
[theView release];
adMobAd = nil;
adMobAd = [self requestNewAdmobView];
if(adMobAd != nil)
{
NSLog(#"AMOB :: adding ADMOBVIEW TO VIEW CONTROLLER!");
[theVC.view addSubview:adMobAd];
[adMobAd release];
}
initialized = YES;
}
else
{
NSLog(#"AMOB :: POST initialization");
if(adMobAd!=nil)
{
NSLog(#"AMOB :: adMobView is present, doing nothing...");
}
else
{
NSLog(#"AMOB :: reinitializing..");
[self reinitializeAdmob];
}
}
}
Here is the [self requestNewAdmobView] function :
- (GADBannerView*) requestNewAdmobView
{
NSLog(#"AMOB :: requestNewAdmobView");
CGRect adFrame = CGRectZero;
NSString * appID = nil;
adMobAd = nil;
if(DEVICE_IPAD)
{
adFrame.size = GAD_SIZE_728x90;
appID = #"id1";
}
else
{
adFrame.size = GAD_SIZE_320x50;
appID = #"id2";
}
GADBannerView * tmp = nil;
tmp = [[GADBannerView alloc] initWithFrame:adFrame];
if(tmp != nil)
{
NSLog(#"AMOB :: adMobAD != nil , commencing with other stuff!");
tmp.adUnitID = appID;
tmp.rootViewController = gD.viewController;
tmp.delegate = self;
[tmp loadRequest:[GADRequest request]];
[tmp setHidden:NO];
}
else
{
NSLog(#"AMOB :: adMobAD == nil , THIS IS BAD..");
}
return tmp;
}
Here is the [self reinitializeAdmob] function :
-(void) reinitializeAdmob
{
NSLog(#"AMOB :: reinitializeAdmob");
if(theViewController != nil)
{
[self shutdownAdmob];
adMobAd = nil;
adMobAd = [self requestNewAdmobView];
if(adMobAd!=nil)
{
[theViewController.view addSubview:adMobAd];
}
}
}
And finally the [self shutdownAdmob]
-(void) shutdownAdmob
{
NSLog(#"AMOB :: shutdownAdmob");
if(adMobAd!=nil)
{
NSLog(#"AMOB :: adMobAd != nil, removing from superview and nilling...");
adMobAd.delegate = nil;
[adMobAd removeFromSuperview];
//[adMobAd release];
adMobAd = nil;
}
else
{
NSLog(#"AMOB :: adMobAd == nil");
}
}
Now from what I understand I am cleaning the GADBannerView called AdMobView correctly because :
at first it is == nil
then in [self requestNewAdmobView] i am allocing an instance so retain count = 1
I am returning it and then adding it to the viewControllers view and the view retains it so that makes the retain count go up to 2
I am then releasing the adMobView so I no longer own it and the retain drops down to 1
then when I want to get rid of the object completely in [self shutdownAdmob] i use the removeFromSupreview function which releases the view from the controller and thus it should dealloc it (I even tested this by subclassing the GADViewController and doing an NSLog upon deallocation and it does indeed dealloc).
Phew.. That's a lot of text sorry for that. So the question is :
why does the admobview remove itself correctly the 1st time but durring the 2nd time it does not.?
You must release the adMobAd in shutdownAdMob.
The removeFromSuperview decreases the reference count of the adMobAd, but
the count was incremented with addSubView, so you must release it.
I've had the same problem. I solved it by selecting this check