0

My requirement is to write a sample IOS app that would automatically capture a camera picture. Using the various S.O links provided I did implement the below code -

My CameraViewController.h class is defined as follows :

@interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>

@property (strong, nonatomic) IBOutlet UIImageView *ImageView;

@end

And CameraViewController.m has the below code :

    -(void)viewDidAppear:(BOOL)animated
{
    NSLog(@"Setting the background now");

    UIImagePickerController *picker = [[UIImagePickerController alloc] init];picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    picker.showsCameraControls = NO;
    picker.navigationBarHidden = NO;
    picker.toolbarHidden = NO;
    [self presentViewController:picker animated:YES completion:NULL];

    NSLog(@"Taking the picture now");
   [picker takePicture];


}


-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{
    NSLog(@"Entered the case of finishing pictures");
}

- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker
{
    NSLog(@"Entered the case of cancel");

}

What the above code does is successfully launch the camera app , however I am not sure if the takePicture API is able to successfully click a picture . I do not see any saved pictures in the Photos app inside my Ipad so I assume that the picture has not been clicked . Can someone please tell me if my code above is correct or what do I need to do to automate the part of clicking the capture button once the Camera controls are displayed

sim
  • 249
  • 7
  • 17

4 Answers4

2

[Please go to 'Using UIImagePickerController to Select Pictures and Take Photos' in the Apple documentation for the property cameraOverlayView of class UIImagePickerController for a complete example application that does what you need, and more.]

You specified your CameraViewController as adopting the UIImagePickerControllerDelegate protocol and thus you must implement two messages:

- (void)   imagePickerController: (UIImagePickerController *) picker      
   didFinishPickingMediaWithInfo: (NSDictionary *) info;

and

- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker;

As the iOS documentation describes, the NSDictionary* info has a key UIImagePickerControllerOriginalImage which will return the UIImage. Access it as something like:

UIImage *snapshot = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];

Since your plan is to take a picture automatically (w/o user interaction) using takePicture then be sure to specify

  picker.showsCameraControls = NO;
GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • I did some more reading today . My requirement is to automatically click the picture once the Camera preview is displayed (the User should not manually click the button on the camera app). My assumption was that the takePicture API will ? In my case the didFinishPickingMediaWithInfo will not work as the user cannot manually click or select the "Use Photo" option – sim Oct 22 '13 at 20:11
  • The Apple documentation requires that you do not show the image picker controls when programmatically calling `takePicture`. See my edit above. – GoZoner Oct 22 '13 at 20:31
  • Okay I did add the image picker controls to No , I have edited my original question with the latest code , but it still does not enter the didFinishPickingMediaWithInfo function . My doubt is does takePicture actually click the picture ? How else will I be able to enter the didFinishPickingMediaWithInfo API ? – sim Oct 22 '13 at 20:41
  • Edited with a note to see the Apple example code that does exactly what you are attempting (and does a bit more too). Good luck. – GoZoner Oct 22 '13 at 21:27
  • I did refer to the example and it was very insightful ,but it still does not solve my problem . I want the app automated to the extent that the user should not even press the customized button , but when I try to call the method myself or simulate the button press the app does not yield the desired result . Should I try adding a timer ? – sim Oct 24 '13 at 20:34
1

You need to implement the UIImagePIckerControllerDelegate's imagePickerController:didFinishPickingMediaWithInfo: method.

After that, look inside the mediaInfo dictionary and there's a UIImage inside it you can use.

David Wong
  • 10,284
  • 3
  • 39
  • 34
  • I added the following code with a log statement , but it does not enter this function , is there something I am missing ? -(void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info { NSLog(@"Entered the case of finishing pictures"); } - (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker { } – sim Oct 22 '13 at 14:45
0

I know this is old, but a better alternative to using a timer (see the comments from the accepted answer) would be to implement the completion handler instead of passing in NULL.

[self presentViewController:picker animated:YES completion:^{
    NSLog(@"Taking the picture now");
    [picker takePicture];
}];

That way, the picture is taken consistently every time, and you don't waste time adding an unnecessary delay.

jabelch
  • 13
  • 2
0
**You can auto capturing both camera image and video recording by use this code.**

import UIKit
import AVFoundation
import MobileCoreServices

class ViewController: UIViewController, UIGestureRecognizerDelegate {

    let captureSession = AVCaptureSession()
    var captureDevice : AVCaptureDevice?
    var imagePicker = UIImagePickerController()
    var flagVideoRecording = false
    var arrImages = [UIImage]()
    var countVideoRecording = 0
    var labelTime = UILabel()
    var timer: Timer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(actionRepeatCapturing), name: .AVCaptureSessionDidStartRunning, object: nil)
    }
    
    @objc func actionRepeatCapturing() {
        flagVideoRecording = false
        startCapturingBothImageAndRecordView()
    }
    
    //MARK:- UIButton's Action
    @IBAction func actionCaptureImage(_ sender: UIButton) {
        flagVideoRecording = false
        
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized {
            startCapturingBothImageAndRecordView()
        } else {
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
                if granted == true {
                    self.startCapturingBothImageAndRecordView()
                } else {
                    DispatchQueue.main.async {
                        self.alertToEncourageAccessInitially("Camera access required for capturing photos!", actionTitle: "Allow Camera")
                    }
                }
            })
        }
    }
    
    @IBAction func actionCaptureVideo(_ sender: UIButton) {
        flagVideoRecording = true
        if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) ==  AVAuthorizationStatus.authorized {
            switch AVAudioSession.sharedInstance().recordPermission {
            case AVAudioSession.RecordPermission.granted:
                self.startCapturingBothImageAndRecordView()
            case AVAudioSession.RecordPermission.denied:
                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
            case AVAudioSession.RecordPermission.undetermined:
                
                AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
                    if granted {
                        self.startCapturingBothImageAndRecordView()
                    } else {
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    }
                })
                
            default:
                break
            }
        } else {
            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
                if granted == true {
                    switch AVAudioSession.sharedInstance().recordPermission {
                    case AVAudioSession.RecordPermission.granted:
                        self.startCapturingBothImageAndRecordView()
                    case AVAudioSession.RecordPermission.denied:
                        self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                    case AVAudioSession.RecordPermission.undetermined:
                        
                        AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
                            if granted {
                                self.startCapturingBothImageAndRecordView()
                            } else {
                                self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
                            }
                        })
                        
                    default:
                        break
                    }
                } else {
                    DispatchQueue.main.async {
                        self.alertToEncourageAccessInitially("Camera access required for record video", actionTitle: "Allow Camera")
                    }
                }
            })
        }
    }
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func startCapturingBothImageAndRecordView() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
            debugPrint("captureVideoPressed and camera available.")
            imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .camera
            if flagVideoRecording {
                imagePicker.mediaTypes = [kUTTypeMovie as String]
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
                
                let viewTime = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 40))
                viewTime.backgroundColor = .black
                viewTime.alpha = 0.1
                labelTime = UILabel(frame: CGRect(x: self.view.frame.width/2-50, y: 10, width: 100, height: 25))
                labelTime.font = UIFont.boldSystemFont(ofSize: 17)
                labelTime.text = "00.00:00"
                labelTime.textColor = .white
                labelTime.textAlignment = .center
                labelTime.backgroundColor = .red
                imagePicker.view.addSubview(viewTime)
                imagePicker.view.addSubview(labelTime)
                
                self.timer = Timer.scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(self.actionStopVideoRecording),
                                     userInfo: nil,
                                     repeats: true)
            } else {
                imagePicker.allowsEditing = false
                imagePicker.showsCameraControls = false
            }
        } else {
            debugPrint("Camera not available.")
        }
        
        
        self.present(self.imagePicker, animated: true, completion: {
            if self.flagVideoRecording {
                self.imagePicker.startVideoCapture()
            } else {
                self.imagePicker.takePicture()
            }
        })
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        if flagVideoRecording {
            if let videoFileURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
                debugPrint(videoFileURL)
                
//                let data = try Data(contentsOf: videoFileURL, options: .mappedIfSafe)
//                debugPrint(data)
            }
            self.dismiss(animated: true, completion: nil)
        } else {
            if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
                arrImages.append(pickedImage)
            }
            
            sleep(1)
            
            if arrImages.count >= 5 {
                self.dismiss(animated: true, completion: nil)
            } else {
                NotificationCenter.default.post(name: .AVCaptureSessionDidStartRunning, object: nil, userInfo: nil)
            }
        }
    }
    
    @objc func actionStopVideoRecording() {
        countVideoRecording += 1
        labelTime.text = countVideoRecording == 10 ? "00:00:\(countVideoRecording)":"00:00:0\(countVideoRecording)"
        
        if countVideoRecording == 10 {
            imagePicker.stopVideoCapture()
            timer?.invalidate()
            timer = nil
        }
    }
}

extension ViewController {
    func alertToEncourageAccessInitially(_ msgString: String, actionTitle: String) {
        let alert = UIAlertController(
            title: "IMPORTANT",
            message: msgString,
            preferredStyle: UIAlertController.Style.alert
        )
        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: actionTitle, style: .destructive, handler: { (alert) -> Void in
            let myUrl = URL(string: UIApplication.openSettingsURLString)!
                if let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty {
                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
                }

                // or outside scope use this
                guard let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty else {
                   return
                }
                 UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }))
        present(alert, animated: true, completion: nil)
    }
}
V.Kumar
  • 139
  • 2
  • 5