8

For some reason the first time I open the UIImagePickerController in camera mode on my app it comes up blank. I have to close and reopen that view to get the camera feed to start working. I'm using the standard code that works in iOS 6 perfectly for camera capture. From the sample below I'm firing the capturePhoto: method. Anyone else running into this jenkiness with the iOS 7 camera? I checked the Apple dev forums but its near impossible to find answers there.

- (IBAction)capturePhoto:(id)sender {
    [self doImagePickerForType:UIImagePickerControllerSourceTypeCamera];
}

- (void)doImagePickerForType:(UIImagePickerControllerSourceType)type {
    if (!_imagePicker) {
        _imagePicker = [[UIImagePickerController alloc] init];
        _imagePicker.mediaTypes = @[(NSString*)kUTTypeImage];
        _imagePicker.delegate = self;
    }
    _imagePicker.sourceType = type;
    [self presentViewController:_imagePicker animated:YES completion:nil];
}

why so empty?

KyleStew
  • 420
  • 1
  • 5
  • 14

4 Answers4

16

I'm also using UIImagePickerController and ran into the same issue with a blank screen. I'd like to expand a little on what klaudz mentioned regarding iOS 7 authorization for the camera.

Reference: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html

"Recording audio always requires explicit permission from the user; recording video also requires user permission on devices sold in certain regions."

Here is some code fragments you can start with to check to see if you have permission for the camera and request it if your app hadn't previously requested it. If you are denied due to an earlier request, your app may need to put up a notice to the user to go into settings to manually enable access as klaudz pointed out.

iOS 7 example

NSString *mediaType = AVMediaTypeVideo; // Or AVMediaTypeAudio

AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];

// This status is normally not visible—the AVCaptureDevice class methods for discovering devices do not return devices the user is restricted from accessing.
if(authStatus == AVAuthorizationStatusRestricted){
    NSLog(@"Restricted");
}

// The user has explicitly denied permission for media capture.
else if(authStatus == AVAuthorizationStatusDenied){
    NSLog(@"Denied");
}

// The user has explicitly granted permission for media capture, or explicit user permission is not necessary for the media type in question.
else if(authStatus == AVAuthorizationStatusAuthorized){
    NSLog(@"Authorized");
}

// Explicit user permission is required for media capture, but the user has not yet granted or denied such permission.
else if(authStatus == AVAuthorizationStatusNotDetermined){

    [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {

        // Make sure we execute our code on the main thread so we can update the UI immediately.
        //
        // See documentation for ABAddressBookRequestAccessWithCompletion where it says
        // "The completion handler is called on an arbitrary queue."
        //
        // Though there is no similar mention for requestAccessForMediaType, it appears it does
        // the same thing.
        //
        dispatch_async(dispatch_get_main_queue(), ^{

            if(granted){
                // UI updates as needed
                NSLog(@"Granted access to %@", mediaType);
            }
            else {
                // UI updates as needed
                NSLog(@"Not granted access to %@", mediaType);
            }
        });

    }];

}

else {
    NSLog(@"Unknown authorization status");
}
Scott Carter
  • 1,254
  • 9
  • 16
  • how can I do that in iOS 6 ? – jianpx Nov 15 '13 at 06:57
  • I am facing issue while capturing image also. how can i resolve it. – Nirav Jain Mar 24 '14 at 06:10
  • where to use this solution? – Nirav Jain Mar 24 '14 at 06:20
  • does this only apply to those "certain regions" (what are these regions anyway?), or to all people? – user102008 Jun 16 '14 at 20:55
  • also, taking a picture seems hardly related to "recording video" – user102008 Jun 16 '14 at 20:57
  • Don't have an answer for iOS 6 - sorry. Solution works for image capture also. I use AVMediaTypeVideo for all camera permissions (image and video) and AVMediaTypeAudio for microphone permissions. I agree with user102008 that a constant other than "AVMediaTypeVideo" would have been better for the purpose of authorizing images and video. I don't know where "regions" are defined, but code fragment should work in all regions. – Scott Carter Jul 01 '14 at 15:26
  • @ScottCarter: Hi Scott. I am using a simple UIImagePickerController to take picture. I was not not facing this problem before iOS 8. But, when I use my code in Xcode 6 (iOS 8 SDK), it is asking user permission. Can I use above method to check camera authorization status? Please clarify. – Rashmi Ranjan mallick Oct 16 '14 at 13:46
  • I would think that the code would be fine in iOS 8. Both authorizationStatusForMediaType and requestAccessForMediaType are available for iOS 7 and later. Let me know if you find out otherwise. – Scott Carter Oct 16 '14 at 18:08
7

In iOS 7, an app could access the camera before getting authorize of the user. When an app accesses the camera the first time, iOS show an alert view to ask user. Users could also set the authorize in Settings--Privacy--Camera--[Your app's name].

The camera will stay in a black blank view if the switch is off.

  1. If you call the camera by using AVCaptureDeviceInput, you can check like:

    NSError *inputError = nil;
    AVCaptureDeviceInput *captureInput =
        [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&inputError];
    if (inputError &&
        inputError.code == AVErrorApplicationIsNotAuthorizedToUseDevice)
    {
        // not authorized
    }
    
  2. If you call by using UIImagePickerController, I am still looking for a way to check whether got the authorize.

    I tried these two methods:

    [UIImagePickerController isSourceTypeAvailable:]
    [UIImagePickerController isCameraDeviceAvailable:]
    

    but they did't work that they all returned YES.

UPDATE

Thanks for Scott's expanding. [AVCaptureDevice authorizationStatusForMediaType:] is a better way to check.

AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusAuthorized) {
    // successful
} else {
    // failed, such as
    // AVAuthorizationStatusNotDetermined
    // AVAuthorizationStatusRestricted
    // AVAuthorizationStatusNotDetermined
}

But remember to check the iOS version, because [AVCaptureDevice authorizationStatusForMediaType:] and AVAuthorizationStatus are available above iOS 7.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    // code for AVCaptureDevice auth checking
}
klaudz
  • 270
  • 1
  • 4
  • What to use in iOS6 for authorisation....your first point which is using 'AVErrorApplicationIsNotAuthorizedToUseDevice' in if condition? – Ashok Dec 16 '13 at 06:16
  • 1
    No settings in PRIVACY in iOS6,so just check by using `[UIImagePickerController isSourceTypeAvailable:]` and ` [UIImagePickerController isCameraDeviceAvailable:]` if you need. – klaudz Dec 17 '13 at 08:56
  • 3
    Instead of `[[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0` you should instead check `[AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]` – user102008 Jun 10 '14 at 19:22
4

I experienced the exact same problem, and tried every solution on the Internet with no luck. But finally I found out it was the background thread prevented the camera preview to show up. If you happen to have background thread running while trying to open the camera as I do, try to block the background thread and see what happens. Hope you can get around it.

Vinson Li
  • 41
  • 2
  • That seems like the likely culprit, I will dig through my code and try and solve this. Thanks for the reply. – KyleStew Sep 29 '13 at 00:04
  • any progress here? i dispatched a TSI for apple but no response, removing GCD from my application is impossible and i just hope there is a way to pause or stop GCD to show the camera if this is remotely true =( – Heavy_Bullets Sep 29 '13 at 06:17
  • I haven't been able to hit on an exact step of events to reproduce it consistently, and something I did in my codebase seems to have solved the issues as I'm no longer seeing the problem. I hope you're able to sort it out as well. – KyleStew Sep 30 '13 at 01:08
  • I tried to remove multithreading and the camera worked well. But my app can't live without GCD as well. Any better ideas? – Vinson Li Sep 30 '13 at 06:23
  • 1
    I had the same problem while using a background `dispatch_async` in the `imagePickerController:didFinishPickingMediaWithInfo` method. Moving that to a separate method and calling it using a `NSThread detachNewThreadSelector:` solved the issue. I am not sure how that background code was affecting the image picker since it was executed and finished way before trying to open the camera again. – Igor N Oct 30 '13 at 09:21
  • Same thing happened to me. I could not find a solution to this issues, but once I stopped all background threads and ran my camera. It worked just as it was intended. Thanks! – AgnosticDev Feb 05 '14 at 13:57
  • @AgnosticDev Can you please give more explanation on how you stopped the background threads and presented your camera. I have the same problem and here is my qn. http://stackoverflow.com/questions/23156920/uiimagepickercontroller-not-showing-taking-more-time-to-load-camera-preview-in – jeevangs Apr 18 '14 at 15:14
  • @jeevangs I was using GCD to execute some tasks while I was opening the camera. Once I removed all of these functionality, everything worked. – AgnosticDev Apr 28 '14 at 10:21
  • I believe I addressed what you're describing by adding a delay before the camera call: [self performSelector:@selector(choosePhoto) withObject:self afterDelay:0.1]; – DenVog Apr 13 '15 at 16:17
0

I came across this control AQPhotoPicker. It's quite easy to use, and hopefully it will help you

aqavi_paracha
  • 1,131
  • 2
  • 17
  • 38