---
id: mobile-camera-ar-patterns
title: Mobile Camera / AR β AVFoundation / CameraX / ARKit
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [mobile, camera, ar, vibe-coding]
tech_stack: { language: "Swift / Kotlin", applicable_to: ["iOS", "Android"] }
applied_in: []
aliases: [AVCaptureSession, CameraX, ARKit, ARCore, RealityKit, Sceneform, AR foundation]
---
# Mobile Camera / AR
> Camera = native API. **AVFoundation (iOS), CameraX (Android), ARKit / ARCore for AR**.
## π ν΅μ¬ κ°λ
- Capture session.
- Frame processing (real-time).
- Permission.
- AR (anchor, plane, light).
## π» μ½λ ν¨ν΄
### iOS Camera (AVFoundation)
```swift
let session = AVCaptureSession()
session.sessionPreset = .high
guard let device = AVCaptureDevice.default(for: .video),
let input = try? AVCaptureDeviceInput(device: device) else { return }
session.addInput(input)
let output = AVCapturePhotoOutput()
session.addOutput(output)
let preview = AVCaptureVideoPreviewLayer(session: session)
preview.frame = view.bounds
view.layer.addSublayer(preview)
session.startRunning()
// Capture
output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
```
### iOS frame processing
```swift
let videoOutput = AVCaptureVideoDataOutput()
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: .userInitiated))
session.addOutput(videoOutput)
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
// λ§€ frame:
// - Vision / Core ML inference.
// - Filter / draw.
}
```
### iOS permission
```xml
NSCameraUsageDescription
Used to take photos.
```
```swift
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted { setupCamera() }
}
```
### Android CameraX
```kotlin
val cameraProvider = ProcessCameraProvider.getInstance(context).get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(viewFinder.surfaceProvider)
}
val imageCapture = ImageCapture.Builder().build()
val analyzer = ImageAnalysis.Builder().build().also {
it.setAnalyzer(executor) { imageProxy ->
// λ§€ frame.
imageProxy.close()
}
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview, imageCapture, analyzer
)
```
β Modern Android camera API.
### CameraX permission
```kotlin
val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) setupCamera()
}
launcher.launch(Manifest.permission.CAMERA)
```
```xml
```
### Photo capture
```swift
// iOS
output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
let data = photo.fileDataRepresentation()
// Save / process.
}
```
```kotlin
// Android
imageCapture.takePicture(
ContextCompat.getMainExecutor(context),
object : ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
// Process.
image.close()
}
}
)
```
### Video record (iOS)
```swift
let movieOutput = AVCaptureMovieFileOutput()
session.addOutput(movieOutput)
let url = FileManager.default.temporaryDirectory.appendingPathComponent('video.mov')
movieOutput.startRecording(to: url, recordingDelegate: self)
// Stop
movieOutput.stopRecording()
```
### Video record (Android)
```kotlin
val recorder = Recorder.Builder().setQualitySelector(QualitySelector.from(Quality.HD)).build()
val videoCapture = VideoCapture.withOutput(recorder)
cameraProvider.bindToLifecycle(lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, videoCapture)
val recording = videoCapture.output
.prepareRecording(context, fileOutputOptions)
.start(executor) { event ->
// Status.
}
// Stop
recording.stop()
```
### iOS ARKit
```swift
import ARKit
import RealityKit
let arView = ARView(frame: view.bounds)
view.addSubview(arView)
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
arView.session.run(config)
// Place 3D object on plane
arView.session.delegate = self
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
for anchor in anchors {
if let plane = anchor as? ARPlaneAnchor {
// Add 3D model.
}
}
}
```
### Android ARCore
```kotlin
// Sceneform λλ ARCore SDK
val session = Session(context)
val config = Config(session)
config.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL
session.configure(config)
// λ§€ frame.
val frame = session.update()
val planes = frame.getUpdatedTrackables(Plane::class.java)
```
β Sceneform κ° deprecated. ARCore μ§μ .
### Cross-platform AR
```
- Unity AR Foundation: Unity μΉν.
- React Native: react-native-arkit / react-native-arcore.
- Flutter: ar_flutter_plugin.
β Native κ° κ°μ₯ κ°λ ₯. Cross-platform κ° limit.
```
### ML on frame
```swift
// iOS Vision + Core ML
let request = VNCoreMLRequest(model: model) { request, error in
// Result.
}
let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer)
try? handler.perform([request])
```
```kotlin
// Android ML Kit
val detector = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
val image = InputImage.fromMediaImage(imageProxy.image!!, imageProxy.imageInfo.rotationDegrees)
detector.process(image).addOnSuccessListener { result ->
// text.
}
```
### Performance
```
60 FPS = 16.7 ms / frame.
ML κ° λ무 λλ¦° = drop frame.
β Background thread.
Smaller model.
Skip frame (every 2nd).
```
### Use case
```
- Photo / video capture.
- QR / barcode (ML Kit / Vision).
- Document scan.
- AR (place, measure).
- Filter (Snapchat μ).
- OCR.
- Face detect (Bumble μ).
```
### Camera permission UX
```
μ¬μ©μ κ° deny ν:
- Settings κ° manual λ³κ²½.
- Re-prompt μ λ¨.
β "Why need" λͺ
ν. 첫 prompt μ μ€.
```
### Battery / heat
```
Camera κ° ν° battery + heat.
- μ¬μ© μ μ stop session.
- λ§€ frame ML κ° νμ μλ§.
- Resolution κ° use case λ°λΌ.
```
### iOS LiDAR (modern)
```swift
let config = ARWorldTrackingConfiguration()
config.sceneReconstruction = .mesh
if ARWorldTrackingConfiguration.supportsSceneReconstruction(.mesh) {
// iPhone Pro μ΄μ.
}
```
β Depth + 3D mesh.
### Photo metadata
```swift
photo.metadata // GPS, exif, ...
```
```kotlin
// CameraX κ° μλ set EXIF.
```
β Privacy μ μ€.
### Streaming (live broadcast)
```
- HLS / DASH λ‘ stream.
- WebRTC (real-time).
β ν° bandwidth.
```
### Filter / effect
```swift
// Core Image
let context = CIContext()
let filter = CIFilter.gaussianBlur()
filter.setValue(ciImage, forKey: kCIInputImageKey)
let output = filter.outputImage
```
β Real-time gauss / sharpen / etc.
### React Native
```
- react-native-vision-camera (modern).
- expo-camera.
- frame processor (worklet for ML).
```
### Flutter
```
- camera plugin.
- image_picker.
- ML κ° λ³ plugin.
```
### Production tips
```
1. Permission flow μ μ€.
2. Resolution = use case λ°λΌ.
3. Background thread (ML).
4. Battery / heat μΈμ§.
5. Privacy (metadata strip).
6. Test κ° λ§€ device (low-end).
```
### ν¨μ
```
- Permission deny: re-prompt μ λ¨.
- High resolution = slow + ν° file.
- ML μ΄ main thread: jank.
- Background = stop session.
- AR κ° λͺ¨λ device μ λ¨ (LiDAR / GPU).
```
## π€ μμ¬κ²°μ κΈ°μ€
| μμ
| μΆμ² |
|---|---|
| iOS native | AVFoundation |
| Android native | CameraX |
| AR iOS | ARKit + RealityKit |
| AR Android | ARCore |
| ML detect | Vision (iOS) / ML Kit (Android) |
| Cross-platform | RN Vision Camera / Flutter camera |
| Document scan | VisionKit (iOS) / ML Kit (Android) |
## β μν°ν¨ν΄
- **Permission deny + no fallback**: bad UX.
- **High res + ML: drop frame.
- **Background + session running**: battery.
- **Metadata κ° store**: privacy leak.
- **AR κ° λ§€ device κ°μ **: μ λ¨.
## π€ LLM νμ© ννΈ
- AVFoundation (iOS) / CameraX (Android) κ° modern.
- ARKit / ARCore κ° native AR.
- ML κ° Vision / ML Kit.
- Resolution + permission + privacy.
## π κ΄λ ¨ λ¬Έμ
- [[Android_CameraX_Patterns]]
- [[iOS_Audio_Video_AVKit]]
- [[Android_ML_Kit_Health]]