Open Camera Programmatically Through iOS App - Deep Link? - ios

I want to create an IBAction to open the iOS native camera app in my app, but I can't seem to find the address for the camera app online.
I know for messages it's: UIApplication.shared.open(URL(string: "sms:")!, options: [:], completionHandler: nil)
Does anyone know which is the correct scheme?

I suggest you to follow a clean way doing so:
let cameraVc = UIImagePickerController()
cameraVc.sourceType = UIImagePickerControllerSourceType.camera
self.present(cameraVc, animated: true, completion: nil)
in such case you must add into the Info.plist:
<key>NSCameraUsageDescription</key>
<string>whatever</string>

Here we suggest you to user the following github :
https://github.com/shantaramk/AttachmentHandler
!. 1. Drag drop the AttachmentHandler folder in project folder
func showCameraActionSheet() {
AttachmentHandler.shared.showAttachmentActionSheet(viewController: self)
AttachmentHandler.shared.imagePickedBlock = { (image) in
let chooseImage = image.resizeImage(targetSize: CGSize(width: 500, height: 600))
self.imageList.insert(chooseImage, at: self.imageList.count-1)
self.collectionView.reloadData()
}
}

Swift 5 version, after adding NSCameraUsageDescription in your Info.plist:
let cameraVc = UIImagePickerController()
cameraVc.sourceType = UIImagePickerController.SourceType.camera
self.present(cameraVc, animated: true, completion: nil)

Related

Xcode Camera: Failed to read exposureBiasesByMode dictionary

I recently got this error with the UIImagePickerController in Xcode Version 12.0.1
[Camera] Failed to read exposureBiasesByMode dictionary: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is NULL" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is NULL}
Has anyone else seen this error? How do you fix it?
If you customize your image picker as imagePicker.allowsEditing = true
you have to fetch image using:
if let pickedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
capturedImage = pickedImage
}
If you instead use imagePicker.allowsEditing = false, use this to pick image:
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
capturedImage = pickedImage
}
If you don't follow this combination, you may get this error.
in my case, I got this bug from trying to use the image data and syncing with Files. Adding this permission in Info.plist made all the difference and made that error go away:
<key>LSSupportsOpeningDocumentsInPlace</key> <true/>
I experienced the same issue. I imported AVKit instead og AVFoundation and tried to present the video in the native recorder view. That gave me an exception telling me to add NSMicrophoneUsageDescription to the info.plist file, and after this, I was able to display the live video in a custom view.
So I believe the issue is with iOS 14 being very picky about permissions, and probably something goes wrong with showing the correct exception when the video is not presented in the native view.
Anyway, this worked for me:
import AVKit
import MobileCoreServices
#IBOutlet weak var videoViewContainer: UIView!
private let imagePickerController = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
initCameraView()
}
func initCameraView() {
// Device setup
imagePickerController.delegate = self
imagePickerController.sourceType = .camera
imagePickerController.mediaTypes = [kUTTypeMovie as String]
imagePickerController.cameraCaptureMode = .video
imagePickerController.cameraDevice = .rear
// UI setup
addChild(imagePickerController)
videoViewContainer.addSubview(imagePickerController.view)
imagePickerController.view.frame = videoViewContainer.bounds
imagePickerController.allowsEditing = false
imagePickerController.showsCameraControls = false
imagePickerController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
And then the added description for the NSMicrophoneUsageDescription in the info.plist file :-)
Hope it will work for you as well!
I managed to solve the problem. In fact, it is not directly related to react-native-image-crop-picker. The problem was that I was using react-native-actionsheet to give the user the option to open the camera or the gallery. When I opened the react-native-actionsheet and pressed one of the options, the camera was superimposing the react-native-actionsheet (modal) which generated a conflict, because apparently in IOS it is not possible for one Modal to overlap the other.
So, to solve the problem, I defined a timeout so that it is possible to close the modal before opening the camera.
I got this error when I tried to copy from a URL I couldn't copy. Which was coming from the mediaURL from the UIImagePickerControllerDelegate.
Basically, what I did was to use UISaveVideoAtPathToSavedPhotosAlbum
Like in this example ⤵️
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.absoluteString) {
UISaveVideoAtPathToSavedPhotosAlbum(url.absoluteString, self, #selector(self.didSaveVideo), nil)
} else {
return /* do something*/
}
#objc private func didSaveVideo(videoPath: String, error: NSError, contextInfo: Any) {}
I found the same error with Xcode 12 & iOS 14 when imagePicker's source type is camera.
But the app is working fine, I could take picture using camera and put it in my collection view cell. Thus, maybe something on Xcode 12 I guess.
#objc func addPerson() {
let picker = UIImagePickerController()
if UIImagePickerController.isSourceTypeAvailable(.camera) {
picker.sourceType = .camera
} else {
fatalError("Camera is not available, please use real device.")
}
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
I faced the same error with Xcode 12 & iOS 14.
But in my case, I used ActionSheet to choose camera or photo library before that. So I changed to open camera just after close that ActionSheet, and it works well.
Hope this will be helpful on your issue.
enum MediaOptions: Int {
case Photos
case Camera
}
func selectImage(mediaType: MediaOptions) {
self.mediaOption = mediaType
let iPicker = UIImagePickerController()
iPicker.delegate = self
iPicker.allowsEditing = false
if mediaType == .Camera {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
iPicker.sourceType = .camera
iPicker.allowsEditing = true
}
} else {
iPicker.sourceType = .photoLibrary
}
self.present(iPicker, animated: true, completion: nil)
self.imagePicker = iPicker
}
func choosePhoto() {
let actionSheet = UIAlertController(title: "Choose", message: "", preferredStyle: .actionSheet)
if UIImagePickerController.isSourceTypeAvailable(.camera) {
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action) -> Void in
actionSheet.dismiss(animated: true) {
self.selectImage(mediaType: .Camera) // Just moved here - inside the dismiss callback
}
}))
}
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action) -> Void in
self.selectImage(mediaType: .Photos)
}))
}
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
In my case, I was missing an Info.plist key for NSCameraUsageDescription.
You should enter the purpose of using camera as the description.
It fixed the crash for me.
Plus, if you don't give the purpose, your app is likely to be rejected.
If like me you have this second message :
[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.
Then you have to add this to your info.plist dictionary:
<key>NSCameraUsageDescription</key>
<string>so you can choose a photo or take a picture for object detection</string>
It solved the problem for me

How to open youtube video in app?

I would like to play youtube video in my app. But I want to open a video to full screen by image(button) clicking. I don't want to create UIWebview. Is it possible?
Use this pod: XCDYouTubeKit.
func StartVideo() {
let ViodeoViewController = AVPlayerViewController()
self.present(ViodeoViewController, animated: true, completion: nil)
XCDYouTubeClient.default().getVideoWithIdentifier("KHIJmehK5OA") { (video: XCDYouTubeVideo?, error: Error?) in
if let streamURL = video?.streamURLs[XCDYouTubeVideoQuality.HD720.rawValue] {
ViodeoViewController.player = AVPlayer(url: streamURL)
} else {
self.dismiss(animated: true, completion: nil)
}
}
}
you can also change other configurations setting with the help of library.
Please follow below links:
This is helper provided by youtube, you can install this pod and can use second link to understand how to integrate in your app
https://github.com/youtube/youtube-ios-player-helper
https://developers.google.com/youtube/v3/guides/ios_youtube_helper

UIDocumentPickerViewController doesn't call the didPickDocument method

I have a document picker, but after selecting a document, the didPickDocumentAt part is never triggered. It was working before I updated swift, is there something that is different now?
func selectDocument(_ sender: UIButton!){
let documentPickerVC = UIDocumentPickerViewController(documentTypes: ["org.openxmlformats.wordprocessingml.document", "com.microsoft.word.doc"], in: UIDocumentPickerMode.import)
documentPickerVC.delegate = self
self.present(documentPickerVC, animated: true, completion: nil)
}
func documentPicker(_ documentPicker: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("file picked: \(url)")
documentPicker.dismiss(animated: true, completion: nil)
}
Nothing is 'failing' either, it just isn't calling that documentPicker method.
I have a similar one for selecting media and that one works fine...
func selectMedia(_ sender: UIButton!){
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){
picker.delegate = self
picker.allowsEditing = false
picker.mediaTypes = [kUTTypeMovie as String]
self.present(picker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[String: Any]) {
let url = info[UIImagePickerControllerMediaURL] as! URL
print("media picked: \(url)")
}
Edit:
I just added the documentPickerWasCancelled method, and for some reason that is being called when I select a document.
Note I am selecting a document from google drive, would that have an affect on anything?
Edit 2:
Answered, uninstalled and reinstalled and it worked. See answer below. Thanks everyone for the suggestions.
The above code looks like it is correct. I uninstalled the google drive app (where I was getting files from) and reinstalled it and then it worked as expected. I also tried from dropbox and that worked as well.
Not sure what was making it fail before.

How to access Cloud drives to import files to my app in swift?

I want to get documents from Cloud services like iCloud , google drive and dropbox on a button click (like in WhatsApp screenshot below), does anyone know how to do it in swift ? Thanks in advance
From your project's capabilities. First enable both the iCloud services and the Key-Sharing, import MobileCoreServices in your class and finally extended the following three classes inside your UIViewController :
UIDocumentMenuDelegate,UIDocumentPickerDelegate,UINavigationControllerDelegate
Implement the following functions :
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
let myURL = url as URL
print("import result : /(myURL)")
}
public func documentMenu(_ documentMenu:UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("view was cancelled")
dismiss(animated: true, completion: nil)
}
How to call all of this? Add the following bit of code to your click function..
func clickFunction(){
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
Click your button. The following menu will pop up ..
In the case of DropBox. Upon clicking on any item. You will be redirected back to your app and the URL will be logged in your terminal.
Manipulate the documentTypes to your need. In my app, Users permitted to Pdf only. So, suit yourself.
kUTTypePDF
Also if you feel like customizing your own menu bar. Add the following code and customize your own function inside the handler
importMenu.addOption(withTitle: "Create New Document", image: nil, order: .first, handler: { print("New Doc Requested") })
Enjoy it.
First enable iCloud documents Capabilitie, see Apple documentation here
The you have to use UIDocumentMenuViewController
let importMenu = UIDocumentMenuViewController(documentTypes: doctypes, inMode: .Import)
importMenu.delegate = self
importMenu.popoverPresentationController?.barButtonItem = self.addButon;
self.presentViewController(importMenu, animated: true, completion: nil)

Share app link to by ActivityViewController iOS swift?

My app is not Live yet. I got the app ID from the App Store Connect. I want to share the app link on social media apps. I used the UIActivityViewController:
let string1 = "itms-apps://itunes.apple.com/app/idXXXXXXX"
let url = NSURL(string: string1)
let shareItems = [UIApplication.sharedApplication().openURL(url!)]
let activityViewController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
Problem: It is not showing some social media apps like WhatsApp.
Solution for Swift 4 or better:
This solution also works on iPad (the solution above crashes on iPad):
if let urlStr = NSURL(string: "https://apps.apple.com/us/app/idxxxxxxxx?ls=1&mt=8") {
let objectsToShare = [urlStr]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
if let popup = activityVC.popoverPresentationController {
popup.sourceView = self.view
popup.sourceRect = CGRect(x: self.view.frame.size.width / 2, y: self.view.frame.size.height / 4, width: 0, height: 0)
}
}
self.present(activityVC, animated: true, completion: nil)
}
This is used to open the site, not to share the app:
[UIApplication.sharedApplication().openURL(url!)]
Do this instead:
if let name = URL(string: "https://itunes.apple.com/us/app/myapp/idxxxxxxxx?ls=1&mt=8"), !name.absoluteString.isEmpty {
let objectsToShare = [name]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
} else {
// show alert for not available
}
for sample see this
The solutions here are all good but it's worth considering implementing the UIActivityItemSource protocol and LinkPresentation framework.
My solution achieves the following:
App icon and title showing at the top of the UIActivityViewController
Direct link to App Store for AirDrop ActivityType
Custom text for messages and emails, including an opportunity to add a link to the app on Google Play if required
Subject for emails
Doesn't use the LPMetaDataProvider fetch request (as described in this WWDC 2019 262 video) so faster to load
0. Init the UIActivityViewController:
Set the items to self:
let activityVC = UIActivityViewController(activityItems: [self], applicationActivities: nil)
Exclude certain ActivityTypes which don't apply:
activityVC.excludedActivityTypes = [.addToReadingList, .assignToContact, .markupAsPDF, .openInIBooks, .saveToCameraRoll]
For iPad set the popoverPresentationController.sourceView or .barButtonItem (this is ignored on iPhone):
activityVC.popoverPresentationController?.sourceView = myButton
Present it:
present(activityVC, animated: true, completion: nil)
1. Implement the required UIActivityItemSource methods
https://developer.apple.com/documentation/uikit/uiactivityitemsource
You must implement the placeholder method which according to the docs:
Placeholder objects do not have to contain any real data but should be configured as closely as possible to the actual data object you intend to provide.
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return ""
}
And the actual data, returning a link to the app for AirDrop and text for everything else:
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
if activityType == .airDrop {
return URL(string: "APP_STORE_URL")!
}
return "Check out the APP_NAME on the App Store: APP_STORE_URL or on the Google Play Store: PLAY_STORE_URL"
}
2. Implement the subject method
From the docs:
For activities that support a subject field, returns the subject for the item.
func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
return "EMAIL_SUBJECT" // e.g. App name
}
3. Implement the LPLinkMetaData method
From the docs:
Returns metadata to display in the preview header of the share sheet.
#available(iOS 13.0, *)
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
let metadata = LPLinkMetadata()
metadata.title = "APP_NAME"
return metadata
}
iPhone solution for Swift 5+
let url = URL(string: "https://apps.apple.com/us/app/id1535629801")!
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
present(vc, animated: true)

Resources