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.
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 am building a map-based app in iOS (Objective-C) using HERE maps, and am new to this. I was successful in implementing navigation but I am facing a hitch in implementing voice instruction for navigation. This is the code that I have:
- (void) beginNavigationMethod {
self.mapView.zoomLevel = 17.0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didUpdatePositionForNavigation) name:NMAPositioningManagerDidUpdatePositionNotification object:[NMAPositioningManager sharedPositioningManager]];
NMAVoiceCatalog *voiceCatalog = [NMAVoiceCatalog sharedVoiceCatalog];
voiceCatalog.delegate = self;
[voiceCatalog updateVoiceCatalog];
[self.navigationManager startTurnByTurnNavigationWithRoute:self.route];
[NMANavigationManager sharedNavigationManager].mapTrackingEnabled = YES;
[NMANavigationManager sharedNavigationManager].mapTrackingAutoZoomEnabled = YES;
[NMANavigationManager sharedNavigationManager].mapTrackingOrientation
= NMAMapTrackingOrientationDynamic;
[NMANavigationManager sharedNavigationManager].speedWarningEnabled = YES;
NSError* error = [[NMANavigationManager sharedNavigationManager] startTurnByTurnNavigationWithRoute:self.route];
NSLog(#"%#",error);
}
- (void)voiceCatalog:(nonnull NMAVoiceCatalog *)voiceCatalog didUpdateWithError:(nullable NSError *)error {
NSLog(#"didUpdateWithError: %#",error);
}
I basically don't know how to proceed with this. My apologies for being so naive. If anyone could guide me through this, it would be a great help.
You can look at docs: https://developer.here.com/documentation/ios-premium/topics/map-voice-instructions.html
Otherwise, where is an example for Android: https://github.com/heremaps/here-android-sdk-examples/issues/36#issuecomment-304873154, if you can go through it it will give you an impression of how to do that.
Please try this code
[[NMANavigationManager sharedNavigationManager] setVoicePackageMeasurementSystem:NMAMeasurementSystemImperialUS];
[[NMAAudioManager sharedAudioManager] setDelegate:self];
[[NMAAudioManager sharedAudioManager]setManagesAudioSession:NO];
Here Map Delegate Method
- (BOOL)audioManager:(NMAAudioManager *)audioManager shouldPlayOutput:(NMAAudioOutput *)output{
return true;
}
Project Setting->General->Capabilities->Background Modes
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;
}
}
I am using EAWiFiUnconfiguredAccessoryBrowser to detect EAWiFiUnconfiguredAccessory. The code to start the accessory search it's the following:
- (void)viewDidLoad {
[super viewDidLoad];
if (_accessories == nil) {
_accessories = [[NSMutableArray alloc] init];
}
if (_browser == nil) {
_browser = [[EAWiFiUnconfiguredAccessoryBrowser alloc] initWithDelegate:self queue:nil];
_browser.delegate = self;
}
}
Unfortunately it does find accessories only the first time the View loads. If I go back to the previous view and then reload the view it does not find them.
I tried:
recreating the browser accessory and restarting the search (does not work)
stopping the search and restarting it (does not work)
This is the latest code I got (refer to this together with the code above):
- (void) viewWillAppear:(BOOL)animated{
NSLog(#"view will appear");
if (_accessories != nil) {
[_accessories removeAllObjects];
}
[self.tableView reloadData];
[self initializeBrowswerAndStartSearch];
}
- (void) initializeBrowswerAndStartSearch{
if (_browser != nil) {
[_browser stopSearchingForUnconfiguredAccessories];
}
[_browser startSearchingForUnconfiguredAccessoriesMatchingPredicate:nil];
}
- (void) viewWillDisappear:(BOOL)animated{
[_browser stopSearchingForUnconfiguredAccessories];
}
It seems that the accessory list information is cached somewhere within the APP. If I restart the APP it will find them so I guess there is something that I am missing.
Any help?
so i have the same problem..you should use the unconfiguredAccessories array. Also, try keeping the instance of the browser alive. If you discover the device once, and you re-instantiate the browser, you wont find it again
EAWiFiUnconfiguredAccessoryBrowser has issues,and doesn't provide reliable result in certain use cases. i think you should try this
- (void) viewWillAppear:(BOOL)animated{
NSLog(#"view will appear");
if (_accessories != nil) {
[_accessories removeAllObjects];
}
[self.tableView reloadData];
[self initializeBrowswerAndStartSearch];
}
below method makes browser object nil and reinitialises it, in this case browser object will always return you updated(i.e, proper) values . it worked perfectly for me.
-(void) initializeBrowswerAndStartSearch
{
// Make EAWiFiUnconfiguredAccessoryBrowser object nil and reinitiate ,start searching again
_browser = nil;
_browser = [[EAWiFiUnconfiguredAccessoryBrowser alloc] initWithDelegate:self queue:nil];
[_browser startSearchingForUnconfiguredAccessoriesMatchingPredicate:nil];
}
anytime you feel EAWiFiUnconfiguredAccessoryBrowser isn't providing proper result , try this.
I also have this issue. So I build a singleton called WAC service, then you can keep this singleton alive during the app life cycle. Anywhere you want to load the unconfigured accissories. Just load it from [_browser unconfiguredAccessories].
I'm preparing to launch my first app and want to have multiple leaderboards inside my game. Currently in sandbox mode I can track and log scores into Game Center successfully. Game Center saves my scores (only if it is higher) and seems to be fully functional.
I know through Itunes Connect we have the ability to set up multiple leaderboards and it seems pretty straight forward. I still want to be able to test multiple leaderboards before publishing my game though. Is there a way to do this in sandbox mode? Currently it seems like my scores are only automatically logged into a default leaderboard. Below is the relevant code I'm using to save/access scores. Thanks!
ABGameKitHelper.m
#pragma mark - Leaderboard
-(void) reportScore:(long long)aScore forLeaderboard:(NSString*)leaderboardId
{
GKScore *score = [[GKScore alloc] initWithCategory:leaderboardId];
score.value = aScore;
[score reportScoreWithCompletionHandler:^(NSError *error) {
if (!error)
{
if(![self hasConnectivity])
{
[self cacheScore:score];
}
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: Reported score (%lli) to %# successfully.", score.value, leaderboardId);
}
else
{
[self cacheScore:score];
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: ERROR -> Reporting score (%lli) to %# failed, caching...", score.value, leaderboardId);
}
}];
}
-(void) showLeaderboard:(NSString*)leaderboardId
{
GKLeaderboardViewController *viewController = [GKLeaderboardViewController new];
viewController.leaderboardDelegate = self;
if (leaderboardId)
{
viewController.category = leaderboardId;
CCLOG(#"Going to category already created");
}
[[self topViewController] presentViewController:viewController animated:YES completion:nil];
}
MainScene.m
- (void)gameCenter {
[[ABGameKitHelper sharedHelper] reportScore:1400 forLeaderboard:#"Score"];
[[ABGameKitHelper sharedHelper] showLeaderboard:#"Score"];
}
I'm not sure if I understand your question properly, but I'll try to answer! Game Center does support multiple leaderboards:
-If you want to send a score to specific leaderboard, you just have to call the function [[ABGameKitHelper sharedHelper] reportScore:X forLeaderboard:LEADERBOARD_ID];, where X represents the score you'd like to send, and LEADERBOARD_ID is the ID of the leaderboard you want to send the score to, as specified in iTunes Connect.
-When you have multiple leaderboards, if you don't want to show just one leaderboard, but a list of them all, you should use the GKGameCenterViewController class instead. However, be careful; this ViewController has been added in iOS 6 only, so you must check which version the device is running. I am also using the ABGameKitHelper, so I've made a function to show this kind of view. Here it goes :
ABGameKitHelper.m
- (void) showGameCenter{
if (![[ABGameKitHelper sharedHelper] hasConnectivity]) return;
//Check if device runs on iOS 5
if([[[UIDevice currentDevice]systemVersion]intValue]==5)
{
//If so, we must use the GKLeaderboardViewController
GKLeaderboardViewController *leaderboard = [[GKLeaderboardViewController alloc] init];
if (leaderboard != nil)
{
leaderboard.leaderboardDelegate = self;
[[self topViewController] presentViewController:leaderboard animated:YES completion:nil];
}
}else if ([[[UIDevice currentDevice]systemVersion]intValue]>=6)
{
//if it runs on iOS 6 or higher, we use GKGameCenterViewController
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.gameCenterDelegate = self;
gameCenterController.viewState = GKGameCenterViewControllerStateDefault;
[[self topViewController] presentViewController:gameCenterController animated:YES completion:nil];
}
}
}
And don't forget to add :
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController{
[gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
}
Using this function will allow you to show a nice view containing all your leaderboards and achievements.
Hope this helps!