Phát hiện sự cho phép của máy ảnh trong iOS


143

Tôi đang phát triển một ứng dụng video rất đơn giản. Tôi sử dụng điều khiển chính thức: UIImagePickerControll.

Đây là vấn đề. Khi trình bày UIImagePickerControll lần đầu tiên, iOS sẽ yêu cầu sự cho phép. Người dùng có thể nhấp vào có hoặc không. Nếu người dùng nhấp vào không, kiểm soát sẽ không bị loại bỏ. Thay vào đó, nếu người dùng tiếp tục nhấp vào nút bắt đầu, bộ hẹn giờ sẽ bật trong khi màn hình luôn màu đen và người dùng không thể dừng bộ hẹn giờ hoặc quay lại. Điều duy nhất người dùng có thể làm là giết ứng dụng. Lần tiếp theo trình bày UIImagePickerCont kiểm soát, nó vẫn là một màn hình đen và người dùng không thể quay lại nếu nhấp vào bắt đầu.

Tôi đã tự hỏi nếu nó là một lỗi. Có cách nào để chúng tôi có thể phát hiện sự cho phép của máy ảnh để chúng tôi có thể quyết định hiển thị UIImagePickerControll hay không?


Re: nó có phải là một lỗi không? IMHO, tôi nghĩ vậy, bởi vì điều dường như xảy ra là VC đang hiển thị dữ liệu từ phần cứng, nhưng về cơ bản HĐH đang gửi không khí chết. Làm thế nào iOS có được ở đây có lẽ là một tác dụng phụ của sự phát triển của gia đình sản phẩm. UIImageViewControllerđược ghi chú là đã được thêm vào iOS 2.0 và các tài liệu không bao giờ được chú thích để phản ánh rằng AVAuthorizationStatus nên được sử dụng, nhưng sống trong một khung khác.
benc

Câu trả lời:


229

Kiểm tra AVAuthorizationStatusvà xử lý các trường hợp đúng.

NSString *mediaType = AVMediaTypeVideo;
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
if(authStatus == AVAuthorizationStatusAuthorized) {
  // do your logic
} else if(authStatus == AVAuthorizationStatusDenied){
  // denied
} else if(authStatus == AVAuthorizationStatusRestricted){
  // restricted, normally won't happen
} else if(authStatus == AVAuthorizationStatusNotDetermined){
  // not determined?!
  [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {
    if(granted){
      NSLog(@"Granted access to %@", mediaType);
    } else {
      NSLog(@"Not granted access to %@", mediaType);
    }
  }];
} else {
  // impossible, unknown authorization status
}

19
cũng yêu cầu: #import <AVFoundation/AVFoundation.h>hoặc tương tự
toblerpwn

9
Một mẹo có thể hữu ích - nếu bạn đang kiểm tra mã sử dụng mã này, bạn không thể xóa Ứng dụng của mình khỏi thiết bị kiểm tra và sau đó cài đặt lại. Làm điều này sẽ không khiến iOS phát hành lại yêu cầu cho người dùng! Điều làm việc cho tôi mặc dù là thay đổi Bundle IDứng dụng mỗi lần tôi muốn kiểm tra điều này. Một cơn đau ở người ăn mày, nhưng ít nhất là một cái gì đó. Chỉ cần nhớ đặt lại ID khi bạn kết thúc ;-)
Stewohn

25
@Benjohn: thay đổi ID Bundle là không cần thiết. Bạn có thể đi tới Cài đặt> Chung> Đặt lại và tìm cài đặt sẽ đặt lại tất cả các lời nhắc cấp phép trên thiết bị. Cấp, điều đó cũng gây phiền nhiễu vì nó cũng ảnh hưởng đến tất cả các ứng dụng khác trên thiết bị của bạn. Giá như Apple có thể thêm các điều khiển dành riêng cho ứng dụng cho phần này trong phần Phát triển của Cài
đặt.app

3
@KennyDeriemaeker :-) Apple có thể trả lời rằng chúng tôi phải sử dụng các thiết bị chuyên dụng để thử nghiệm! Đối với tôi, các tác dụng phụ của việc đặt lại điện thoại thông thường của tôi sẽ rất khó khăn. Thay đổi gói Id là một sự thay thế hợp lý không gây đau đớn. Tôi nhớ để thay đổi nó trở lại trước khi gửi quá :-)
Stewohn

8
Chỉ cần chắc chắn rằng bạn không thực hiện thiết lập lại đầy đủ! Chỉ cần đặt lại cài đặt Quyền riêng tư & Vị trí (iOS 8) là đủ.
Canucklesandwich

81

Swift 4 và mới hơn

Đảm bảo:

import AVFoundation

Mã dưới đây kiểm tra tất cả các trạng thái cho phép có thể:

let cameraMediaType = AVMediaType.video
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: cameraMediaType)
    
switch cameraAuthorizationStatus {
case .denied: break
case .authorized: break
case .restricted: break

case .notDetermined:
    // Prompting user for the permission to use the camera.
    AVCaptureDevice.requestAccess(for: cameraMediaType) { granted in
        if granted {
            print("Granted access to \(cameraMediaType)")
        } else {
            print("Denied access to \(cameraMediaType)")
        }
    }
}

Vì iOS 10, bạn cần chỉ định NSCameraUsageDescriptionkhóa trong Info.plist để có thể yêu cầu quyền truy cập máy ảnh, nếu không ứng dụng của bạn sẽ bị sập khi chạy. Xem API yêu cầu mô tả sử dụng .


Là một lưu ý phụ thú vị, bạn có biết rằng iOS sẽ giết ứng dụng nếu nó chạy trong khi bạn thay đổi quyền của máy ảnh trong Cài đặt không?

Từ diễn đàn Nhà phát triển của Apple:

Hệ thống thực sự sẽ giết ứng dụng của bạn nếu người dùng bật quyền truy cập ứng dụng của bạn vào camera trong Cài đặt. Điều tương tự cũng áp dụng cho mọi dữ liệu được bảo vệ trong phần Cài đặt → Quyền riêng tư.


Điều gì về việc ủy ​​quyền máy ảnh và thư viện ảnh ??
Hajar ELKOUMIKHI

4

Giải pháp Swift

extension AVCaptureDevice {
    enum AuthorizationStatus {
        case justDenied
        case alreadyDenied
        case restricted
        case justAuthorized
        case alreadyAuthorized
        case unknown
    }

    class func authorizeVideo(completion: ((AuthorizationStatus) -> Void)?) {
        AVCaptureDevice.authorize(mediaType: AVMediaType.video, completion: completion)
    }

    class func authorizeAudio(completion: ((AuthorizationStatus) -> Void)?) {
        AVCaptureDevice.authorize(mediaType: AVMediaType.audio, completion: completion)
    }

    private class func authorize(mediaType: AVMediaType, completion: ((AuthorizationStatus) -> Void)?) {
        let status = AVCaptureDevice.authorizationStatus(for: mediaType)
        switch status {
        case .authorized:
            completion?(.alreadyAuthorized)
        case .denied:
            completion?(.alreadyDenied)
        case .restricted:
            completion?(.restricted)
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: mediaType, completionHandler: { (granted) in
                DispatchQueue.main.async {
                    if granted {
                        completion?(.justAuthorized)
                    } else {
                        completion?(.justDenied)
                    }
                }
            })
        @unknown default:
            completion?(.unknown)
        }
    }
}

Và sau đó để sử dụng nó, bạn làm

AVCaptureDevice.authorizeVideo(completion: { (status) in
   //Your work here
})

Điều gì về việc ủy ​​quyền máy ảnh và thư viện ảnh ??
Hajar ELKOUMIKHI

2

Là một bổ sung cho câu trả lời từ @Raptor nên được đề cập sau đây. Bạn có thể nhận được lỗi sau bắt đầu với iOS 10:This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.

Để khắc phục điều này, hãy đảm bảo bạn xử lý các kết quả từ luồng chính như sau (Swift 3):

private func showCameraPermissionPopup() {
    let cameraMediaType = AVMediaTypeVideo
    let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: cameraMediaType)

    switch cameraAuthorizationStatus {
    case .denied:
        NSLog("cameraAuthorizationStatus=denied")
        break
    case .authorized:
        NSLog("cameraAuthorizationStatus=authorized")
        break
    case .restricted:
        NSLog("cameraAuthorizationStatus=restricted")
        break
    case .notDetermined:
        NSLog("cameraAuthorizationStatus=notDetermined")

        // Prompting user for the permission to use the camera.
        AVCaptureDevice.requestAccess(forMediaType: cameraMediaType) { granted in
            DispatchQueue.main.sync {
                if granted {
                    // do something
                } else {
                    // do something else
                }
            }
        }
    }
}

Trong trường hợp bị từ chối, phương thức requestAccess sẽ không hoạt động. Bạn sẽ phải tự hiển thị cảnh báo để yêu cầu người dùng truy cập cài đặt và cấp quyền.
Abdullah Umer

0

Trước tiên, chỉ định khóa NSCameraUsageDes mô tả trong Info.plist. Sau đó kiểm tra AVAuthorizationStatus nếu Được ủy quyền rồi trình bày UIImagePickerControll. Nó sẽ làm việc.


-4

Swift: Sử dụng AVFoundation

  1. Thêm AVFoundation vào Target -> Build Phase -> Link Binary with Library.
  2. nhập AVFoundation trên ViewContoder.
  3. Trên Info.plist, Thêm vào như sau:

nhập mô tả hình ảnh ở đây

  1. Trên điều khiển xem:

@IBAction func cameraButtonClicky (người gửi: AnyObject) {

let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
print(authorizationStatus.rawValue)

if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) ==  AVAuthorizationStatus.Authorized{
    self.openCameraAfterAccessGrantedByUser()
}
else
{
    print("No Access")

    dispatch_async(dispatch_get_main_queue()) { [unowned self] in
        AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted :Bool) -> Void in
            if granted == true
            {
                // User granted
                self.openCameraAfterAccessGrantedByUser()
            }
            else
            {
                // User Rejected
                  alertToEncourageCameraAccessWhenApplicationStarts()
            }
        });
    }
}


//Open camera

    func openCameraAfterAccessGrantedByUser()
    {
    if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
        self.cameraAndGalleryPicker!.sourceType = UIImagePickerControllerSourceType.Camera
        cameraAndGalleryPicker?.delegate = self
        cameraAndGalleryPicker?.allowsEditing =  false
        cameraAndGalleryPicker!.cameraCaptureMode = .Photo
        cameraAndGalleryPicker!.modalPresentationStyle = .FullScreen
        presentViewController(self.cameraAndGalleryPicker!, animated: true, completion: nil)
    }
    else
    {

    }
}

//Show Camera Unavailable Alert

func alertToEncourageCameraAccessWhenApplicationStarts()
    {
        //Camera not available - Alert
        let cameraUnavailableAlertController = UIAlertController (title: "Camera Unavailable", message: "Please check to see if it is disconnected or in use by another application", preferredStyle: .Alert)

let settingsAction = UIAlertAction(title: "Settings", style: .Destructive) { (_) -> Void in
    let settingsUrl = NSURL(string:UIApplicationOpenSettingsURLString)
    if let url = settingsUrl {
        dispatch_async(dispatch_get_main_queue()) {
            UIApplication.sharedApplication().openURL(url)
        }

    }
}
let cancelAction = UIAlertAction(title: "Okay", style: .Default, handler: nil)
cameraUnavailableAlertController .addAction(settingsAction)
cameraUnavailableAlertController .addAction(cancelAction)
self.window?.rootViewController!.presentViewController(cameraUnavailableAlertController , animated: true, completion: nil)
}

Những gì với các mục Info.plist? Nguồn?
Hóa đơn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.