Hello everyone.
I just wanted to share my solution to all of you who has no idea about xCode and found a lot of problems trying to check camera permissions. After a lot of research I got what I think is a good solution. I have modified leonmoodley snippet to include a couple of interesting features (thank you btw, you saved my life!):
- including a button to go directly to the settings page in the message shown to the user, and
- include a couple of variables set from xCode in PlayerPrefs that will be accesible from Unity in case you want, in example, modify your UI according to the user choice.
Just go to the file UnityAppController.mm in the classes folder, and add this line as already described:
#import <AVFoundation/AVFoundation.h>
Look for the function didFinishLaunchingWithOptions and replace it with this one:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
[[NSUserDefaults standardUserDefaults] setInteger: 0 forKey: @"CameraCheckDone"];
// Determine camera access on iOS >= 7
if ([AVCaptureDevice respondsToSelector:@selector(requestAccessForMediaType:completionHandler:)])
{
// Completion handler will be dispatched on a separate thread
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted)
{
if (YES == granted)
{
[[NSUserDefaults standardUserDefaults] setInteger: 1 forKey: @"CameraAccessGranted"];
// User granted access to the camera, continue with app launch
}
else
{
// User denied camera access
// warn the user that the app requires camera access
// and ideally provide some guidance about the device Settings
[[NSUserDefaults standardUserDefaults] setInteger: 0 forKey: @"CameraAccessGranted"];
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Camera permission needed"
message:@"Please change review your configuration and restart the app."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message addButtonWithTitle:@"Settings"];
dispatch_async(dispatch_get_main_queue(), ^{
[message show];
});
}
}];
}
else {
// iOS < 7 (camera access always OK)
[[NSUserDefaults standardUserDefaults] setInteger: 1 forKey: @"CameraAccessGranted"];
// Continue with app launch...
}
[[NSUserDefaults standardUserDefaults] setInteger: 1 forKey: @"CameraCheckDone"];
printf_console("-> applicationDidFinishLaunching()\n");
// get local notification
if (&UIApplicationLaunchOptionsLocalNotificationKey != nil)
{
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (notification)
UnitySendLocalNotification(notification);
}
// get remote notification
if (&UIApplicationLaunchOptionsRemoteNotificationKey != nil)
{
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification)
UnitySendRemoteNotification(notification);
}
if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[DisplayManager Initialize];
_mainDisplay = [[[DisplayManager Instance] mainDisplay] createView:YES showRightAway:NO];
_window = _mainDisplay->window;
[KeyboardDelegate Initialize];
[self createViewHierarchy];
[self preStartUnity];
UnityInitApplicationNoGraphics([[[NSBundle mainBundle] bundlePath]UTF8String]);
return YES;
}
You should add to the file also this function that will manage the "Settings" button click (thank you, Toywheel):
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) // Settings clicked
{
if (&UIApplicationOpenSettingsURLString != NULL) {
NSURL *appSettings = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:appSettings];
}
}
}
After this, you can access from Unity to this two variables stored in PlayerPrefs: CameraCheckDone and CameraAccessGranted, in such a way that you could do somthing like this:
public IEnumerator CheckPrefs()
{
while (!PlayerPrefs.HasKey("CameraCheckDone") || !(PlayerPrefs.GetInt("CameraCheckDone") == 1))
{
yield return new WaitForSeconds(0.25f);
}
while (!PlayerPrefs.HasKey("CameraAccessGranted"))
{
yield return new WaitForSeconds(0.25f);
}
if (PlayerPrefs.GetInt("CameraAccessGranted") == 1)
{
//Permissions granted
}
else
{
//No camera permissions
}
}
I hope this helps! Just remeber that I have no idea about xCode so my code is probably a mess. I just wanted to share my results in case I could save some time and pain to any other.
Happy coding!
Aernarion
alvaroem
AWESOME!
Thanks