70

I'm writing an iOS app, and I need to be able to detect if the device has a camera. Previously, I would check if the device is an iPhone or not, since only the iPhone has a camera - but with the launch of the iPod Touch 4 this is no longer a viable option. The app functions without a camera, but the presence of a camera adds functionality.

So, can anyone provide me with code that returns whether there is a camera or not?

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Origamiguy
  • 1,294
  • 2
  • 13
  • 19

8 Answers8

170

You can use +isSourceTypeAvailable: method in UIImagePickerController:

if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
   // Has camera
Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • 6
    Careful: If the camera is "restricted", this will return false even if a camera exists. – pulse4life Sep 26 '16 at 20:29
  • I am working on an app right now with camera access set to restricted but this is returning true, so @pulse4life's comment is not correct (at least not anymore – using iOS 10). For access authorization you should use `AVAuthorizationStatus`. – shim Jun 05 '17 at 18:57
  • 3
    I just tested this again on iOS 10.3.2. It will return false if the camera has been restricted on your device. By restricted I mean go to Settings>General>Restrictions and turn off the camera (this is usually done by a system admin). I believe this is the intended behavior apple wanted as it is technically not available even though a camera exists. – pulse4life Jun 06 '17 at 18:19
  • However, sometimes my iPhone camera doesn’t work right, which can be either software or hardware related.. How to find out camera working or not in programmatically in swift or objective c? – vikramarkaios Oct 30 '18 at 10:22
  • @vikramarkaios, you mean in cases when the camera malfunctions for some reason? I doubt there's API to detect that. – Vladimir Oct 30 '18 at 16:01
  • @Vladimir, Please let me know what's that api? – vikramarkaios Nov 09 '18 at 06:06
  • @vikramarkaios what I meant, I think that api does not exist – Vladimir Nov 09 '18 at 15:46
27

As Juan Boero wrote check the:

    if UIImagePickerController.isSourceTypeAvailable(.camera) {...}

But I would add another check to see if the user allowed access to camera as apple suggests in their PhotoPicker example (PhotoPicker example Objective-C):

*please note you have to import AVFoundation

SWIFT 5

    let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
    switch authStatus {
        /*
         Status Restricted -
         The client is not authorized to access the hardware for the media type. The user cannot change the client's status, possibly due to active restrictions such as parental controls being in place.
         */
    case .denied, .restricted:
        // Denied access to camera
        // Explain that we need camera access and how to change it.
        let dialog = UIAlertController(title: "Unable to access the Camera", message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.", preferredStyle: UIAlertController.Style.alert)

        let okAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)

        dialog.addAction(okAction)
        self.present(dialog, animated:true, completion:nil)
    case .notDetermined:
        // The user has not yet been presented with the option to grant access to the camera hardware.
        // Ask for it.
        AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (grantd) in
        // If access was denied, we do not set the setup error message since access was just denied.
           if grantd {
           // Allowed access to camera, go ahead and present the UIImagePickerController.
            self.showImagePickerForSourceType(sourceType: UIImagePickerController.SourceType.camera)
            }
        })
    case .authorized:
        // Allowed access to camera, go ahead and present the UIImagePickerController.
        self.showImagePickerForSourceType(sourceType: UIImagePickerController.SourceType.camera)
    @unknown default:
        break; //handle other status
    }

SWIFT 3

let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
    
if authStatus == AVAuthorizationStatus.denied {
    // Denied access to camera
    // Explain that we need camera access and how to change it.
    let dialog = UIAlertController(title: "Unable to access the Camera", message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.", preferredStyle: UIAlertControllerStyle.alert)
        
    let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)
        
    dialog.addAction(okAction)
    self.present(dialog, animated:true, completion:nil)
        
} else if authStatus == AVAuthorizationStatus.notDetermined {     // The user has not yet been presented with the option to grant access to the camera hardware.
    // Ask for it.
    AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (grantd) in
    // If access was denied, we do not set the setup error message since access was just denied.
       if grantd {
       // Allowed access to camera, go ahead and present the UIImagePickerController.
            self.showImagePickerForSourceType(sourceType: UIImagePickerControllerSourceType.camera)
        }
    })
} else {
        
    // Allowed access to camera, go ahead and present the UIImagePickerController.
    self.showImagePickerForSourceType(sourceType: UIImagePickerControllerSourceType.camera)

}

func showImagePickerForSourceType(sourceType: UIImagePickerControllerSourceType) {
    
    let myPickerController = UIImagePickerController()
    myPickerController.delegate = self;
    myPickerController.sourceType = sourceType  
    self.present(myPickerController, animated: true, completion: nil)
}
Boaz Frenkel
  • 618
  • 5
  • 15
  • 2
    As of May 2018, The authorization status can be one of {authorized,notDetermined,denied,restricted} - the restricted status (i.e. an admin has blocked the user from using the camera at all) is not handled above. You may want to `switch` in stead of `if {} else if {}` if this is important to your use case. – ReactiveRaven May 21 '18 at 22:35
23

If you are using the AV Foundation classes instead of UIImagePickerController you can do:

BOOL hasCamera = ([[AVCaptureDevice devices] count] > 0);

If you are using UIImagePickerController it probably isn't worth it, since you'd have to add AVFoundation.framework to your project.

prewett
  • 1,587
  • 14
  • 19
  • 20
    This doesn't necessarily work. If restrictions have turned the camera of, this could output the microphone as a device, but no camera would be available. Better to use [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count] – Jbryson Aug 26 '14 at 17:05
20

Yes, there is an API provided to do just that:

BOOL isCamera = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
12

Swift:

if UIImagePickerController.isSourceTypeAvailable(.Camera){

    //Your code goes here
    //For example you can print available media types:

    print(UIImagePickerController.availableMediaTypesForSourceType(.Camera))

    }
Juan Boero
  • 6,281
  • 1
  • 44
  • 62
6

If you need to know whether the device specifically has a front or rear camera, use this:

isCameraAvailable = [UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront];
RawMean
  • 8,374
  • 6
  • 55
  • 82
0

You can check for availability of a specific source type using discovery session (Swift 5):

let discovery = AVCaptureDevice.DiscoverySession.init(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back)
let isWideAngleCameraSupported = !discovery.devices.isEmpty
Jovan Stankovic
  • 4,661
  • 4
  • 27
  • 16
-1

To check of camera is available (Swift)

if(!UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera))
Usman Nisar
  • 3,031
  • 33
  • 41