Launch The Main App from LockedCameraCapture

If the app is launched from LockedCameraCapture and if the settings button is tapped, I need to launch the main app.

CameraViewController:

func settingsButtonTapped() {
  #if isLockedCameraCaptureExtension
  //App is launched from Lock Screen
     
    //Launch main app here...

  #else
  //App is launched from Home Screen
    self.showSettings(animated: true)
  #endif
}

In this document:

https://developer.apple.com/documentation/lockedcameracapture/creating-a-camera-experience-for-the-lock-screen

Apple asks you to use:

func launchApp(with session: LockedCameraCaptureSession, info: String) {
	Task {
		do {
			let activity = NSUserActivityTypeLockedCameraCapture
			activity.userInfo = [UserInfoKey: info]
			try await session.openApplication(for: activity)
		} catch {
			StatusManager.displayError("Unable to open app - \(error.localizedDescription)")
		}
	}
}

However, the documentation states that this should be placed within the extension code - LockedCameraCapture. If I do that, how can I call that all the way down from the main app's CameraViewController?

let activity = NSUserActivityTypeLockedCameraCapture
activity.userInfo = [UserInfoKey: info]

This is also giving an error after being unrecognized, even after minimum target set to iOS 18.

Did you even able to make the app listed in Camera Control app list?

I added the Capture Extension to my app, but it doesn't appear in the Camera Control app list...

Hi @sle39lvr, great question! You need to hold onto the LockedCameraCaptureSession object that gets passed to you when the extension starts up. There are several ways to do that.

** Option 1 - Pass the Session Down**

When you create your LockedCameraCaptureUIScene, you get that session object in the closure. Just pass it along to your view controller:

  @main
  struct MyCameraExtension: LockedCameraCaptureExtension {
      var body: some LockedCameraCaptureExtensionScene {
          LockedCameraCaptureUIScene { session in
              CameraViewControllerRepresentable(session: session)
          }
      }
  }

  struct CameraViewControllerRepresentable: UIViewControllerRepresentable {
      let session: LockedCameraCaptureSession

      func makeUIViewController(context: Context) -> CameraViewController {
          let vc = CameraViewController()
          vc.captureSession = session  // Pass it here!
          return vc
      }

      func updateUIViewController(_ uiViewController: CameraViewController, context: Context) {}
  }

Then add a property in your CameraViewController to hold it:

  var captureSession: LockedCameraCaptureSession?

** Option 2 - Use a Static Variable**

You can also store the session object in a static variable:

  import LockedCameraCapture

   enum CaptureSessionHolder {
      static var session: LockedCameraCaptureSession?
  }

Store it when your extension starts:

  LockedCameraCaptureUIScene { session in
      CaptureSessionHolder.session = session
      return CameraViewControllerRepresentable()
  }

Then use it in your CameraViewController:

  func settingsButtonTapped() {
      #if canImport(LockedCameraCapture)
      if let session = CaptureSessionHolder.session {
          Task {
              let activity = NSUserActivity(activityType: NSUserActivityTypeLockedCameraCapture)
              try await session.openApplication(for: activity)
          }
      } else {
          showSettings(animated: true)
      }
      #else
      showSettings(animated: true)
      #endif
  }

I noticed that the documentation example has a small bug - NSUserActivityTypeLockedCameraCapture is just a String constant, so you need to wrap it in NSUserActivity(activityType: ...) to actually create the activity object. I'll make sure to fix that bug in the documentation. Thanks for bringing that up!

Hope this helps! Please let me know if you have any further questions.

Launch The Main App from LockedCameraCapture
 
 
Q