CameraX 1.7.0-alpha02 landed on July 1, 2026, and it's one of the denser alpha drops I've seen from this library. Most CameraX releases move one or two things forward; this one touches six or seven distinct surfaces simultaneously — gestures, low-light detection, GPU pipeline access, video quality, focus metering, and concurrent camera styling. None of it ships in stable yet, but the API shapes are clear enough that it's worth understanding them now rather than being surprised when 1.7.0 stabilizes.
I've built camera features into a few different apps — HailUp uses video recording, Musist captures thumbnails, OnlyArabs does live video streaming. Each time, I've had to bolt the same things on manually: a gesture detector for pinch-to-zoom, custom focus metering logic, separate handling for low-light modes. The alpha02 direction is clearly about collapsing that boilerplate into the library itself, which is the right call.
1. CameraXViewfinder Gets Built-In Gestures
If you've ever implemented a camera preview with pinch-to-zoom and tap-to-focus from scratch, you know the amount of code involved. You wire a ScaleGestureDetector to a PreviewView touch listener, map pinch ratios to zoom ratio ranges from CameraInfo, call CameraControl.setZoomRatio(), then separately handle single-tap events by converting the tap point from view coordinates to sensor coordinates and feeding it into CameraControl.startFocusAndMetering(). It works, but it's boilerplate every camera app writes and every camera app writes slightly differently.
Alpha02 adds built-in pinch-to-zoom and tap-to-focus support directly into CameraXViewfinder. You no longer implement the gesture pipeline manually — the viewfinder handles touch events, computes the correct zoom ratio, and calls into CameraControl internally. Screen flash support and stream state observation also land in the same update.
Alongside this, FocusState is now public in viewfinder-core. Previously, you had to observe the ListenableFuture returned from startFocusAndMetering() and interpret the result yourself. With FocusState exposed, you can observe focus state directly from the viewfinder and react to it in your UI — show a focus ring animation, change a button affordance, whatever your design needs — without duplicating the focus result parsing logic.
Why this matters for real apps: the gesture wiring is almost always identical across apps, but the bugs in custom implementations differ. Pixel density conversions done wrong produce a tap-to-focus region that's slightly off. Pinch velocity not clamped correctly causes jarring zoom jumps at the extremes. Baking this into the library means one implementation, tested across hardware, instead of N slightly-broken custom versions.
2. Night Mode Indicator API
Low-light camera handling has been a pain point since forever. You can observe CameraInfo.exposureState to get current exposure values, but knowing whether the camera is actually "in night mode" — whatever that means on a given device — required vendor-specific extensions and a lot of guesswork about what the HAL was doing internally.
Alpha02 adds CameraInfo.isNightModeIndicatorSupported() and CameraInfo.getNightModeIndicator(). The indicator returns a LiveData<Int> whose values tell you whether the camera is detecting a low-light scene and has activated enhanced processing for it. The same API is available on CameraExtensionsInfo for apps using Camera Extensions.
val nightModeIndicator = cameraInfo.getNightModeIndicator()
nightModeIndicator?.observe(viewLifecycleOwner) { mode ->
when (mode) {
CameraInfo.NIGHT_MODE_INDICATOR_OFF -> hideNightModeUI()
CameraInfo.NIGHT_MODE_INDICATOR_ON -> showNightModeUI()
}
}
The practical use case is telling your user something useful. Instead of silently running enhanced processing, you can show a small indicator in your viewfinder UI — "Night Mode Active" — exactly like the stock camera app does, but now with a supported API rather than reverse-engineering it. You can also adapt your capture settings or UI affordances based on whether night mode is active. And isNightModeIndicatorSupported() gives you a clean gate so you don't try to observe the indicator on hardware that doesn't surface this information.
3. GPU-Based ImageAnalysis
This one is the most architecturally significant change in the alpha. ImageAnalysis has always given you CPU-accessible images via ImageProxy. That's fine for ML Kit, for software-based face detection, for anything that needs to read pixel data on the CPU. But if you're feeding frames into a GPU-based processing pipeline — a custom Metal-style render, a shader that composites a real-time filter, a compute shader doing background subtraction — the round-trip through CPU memory has always been a bottleneck. You get the image, copy it to a texture, upload it to GPU memory. That copy is expensive, especially at high resolutions.
Alpha02 exposes ImageAnalysis.OUTPUT_IMAGE_FORMAT_PRIVATE as a public API. Combined with the newly public ImageProxy.getHardwareBuffer(), you can now get camera frames directly as HardwareBuffer objects — GPU-accessible memory that you can wrap in an ImageReader with HardwareBuffer backing, or import directly into EGL/Vulkan/OpenGL as an external texture, with no CPU round-trip.
val imageAnalysis = ImageAnalysis.Builder()
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_PRIVATE)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(executor) { imageProxy ->
val hardwareBuffer = imageProxy.hardwareBuffer
if (hardwareBuffer != null) {
// import into your GPU pipeline — no CPU copy
processOnGpu(hardwareBuffer)
}
imageProxy.close()
}
Where this unlocks new things: real-time augmented reality effects, custom GPU-based background replacement, live filter compositing on the camera feed. All of these have been technically possible but practically slow because of the CPU round-trip. PRIVATE format with HardwareBuffer removes that ceiling.
One important constraint: OUTPUT_IMAGE_FORMAT_PRIVATE images cannot be read by the CPU. The buffer is GPU-only. If your analysis logic needs to read pixel values (for classification, for example), you still use the default OUTPUT_IMAGE_FORMAT_YUV_420_888. This is a pipeline choice — GPU-native processing or CPU-accessible pixels, not both on the same ImageAnalysis instance.
4. QHD Recording and Granular Audio Controls
Alpha02 adds QHD to the supported Quality values in VideoCapture. On hardware that supports it, you can now request quad-HD (2560×1440) recording without falling back to a custom QualitySelector workaround. If the device doesn't support QHD, the selector falls through to the next best quality as usual.
More interesting for production apps are the new audio controls on Recorder.Builder:
val recorder = Recorder.Builder()
.setTargetAudioChannelCount(2) // stereo
.setTargetAudioEncodingBitRate(192_000) // 192 kbps
.setAudioMimeType(MediaFormat.MIMETYPE_AUDIO_AAC)
.setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)
.build()
Previously, audio channel count and bitrate were whatever CameraX decided. If you needed stereo audio or a specific bitrate for upload pipeline compatibility, you had to post-process the recording or use a lower-level API. Now you set it directly on the builder. The companion methods Recorder.getSupportedVideoMimeTypes() and getSupportedAudioMimeTypes() let you query what the device actually supports before committing to a format, and Recorder.getVideoCapabilities(CameraInfo, String) gives you codec-specific quality tiers for a given MIME type. No more guessing whether HEVC at QHD is actually achievable on the current hardware.
5. AE/AWB Locking in Focus Metering
Standard tap-to-focus locks auto-exposure (AE), auto-white-balance (AWB), and auto-focus (AF) together, because that's the most common user intent: tap somewhere, lock everything, capture. But there are scenarios where you want to update the focus region without locking exposure. Portrait mode tap-to-focus is one — you want sharp focus on the new subject, but you don't want to freeze exposure compensation because the lighting balance across the scene changes as the subject moves. Continuous autofocus for video is another — you're tracking subject movement, so focus should track too, but locking exposure mid-shot would produce visible banding.
Alpha02 adds FocusMeteringAction.Builder.setLockingMode() with fine-grained control over which 3A systems get locked on metering:
val meteringPoint = viewfinder.meteringPointFactory.createPoint(x, y)
val action = FocusMeteringAction.Builder(meteringPoint)
.setLockingMode(FocusMeteringAction.LOCKING_MODE_AF_ONLY) // lock AF, keep AE/AWB running
.build()
camera.cameraControl.startFocusAndMetering(action)
The modes let you lock any combination of AF, AE, and AWB independently. LOCKING_MODE_AF_ONLY is the most common need — update focus region while letting exposure and white balance continue to auto-adapt. This is also what you need to implement proper continuous autofocus tracking: call startFocusAndMetering() repeatedly as the subject moves, with AF-only locking so the exposure drift that would normally occur on each metering call is suppressed.
6. Concurrent Camera Composition Styling
Concurrent camera — showing two camera streams simultaneously in a picture-in-picture or side-by-side layout — landed in an earlier release. Alpha02 adds visual styling controls for how those streams are composed:
- Rounded corners via
setRoundedCornerRatio(float)— a normalized value from 0.0 (square) to 1.0 (fully circular). Useful for the PiP-style "floating oval" look that video call apps use. - Borders via
setBorderWidthRatio(float)andsetBorderColor(int)— adds a colored stroke around the composited stream. Useful for making the secondary stream visually distinct from the primary preview. - Dynamic updates via
ConcurrentCamera.setCompositionSettings()— lets you animate composition changes at runtime rather than rebuilding the pipeline. Useful for transitions between layouts.
val compositionSettings = CompositionSettings.Builder()
.setRoundedCornerRatio(0.5f) // pill shape
.setBorderWidthRatio(0.02f)
.setBorderColor(Color.WHITE)
.build()
concurrentCamera.setCompositionSettings(compositionSettings)
These are cosmetic, but they're the kind of cosmetic that previously required a custom compositor or a SurfaceView overlay. Baking styling into the CompositionSettings API means less custom rendering code and more consistent behavior across device profiles.
7. Auto-Rotation and CameraController Expansion
isAutoRotationEnabled is a new property on SessionConfig.Builder, HighSpeedVideoSessionConfig.Builder, and ExtensionSessionConfig.Builder. When enabled, CameraX automatically rotates the camera output based on device sensor orientation — the same thing you'd otherwise compute manually by listening to OrientationEventListener and calling ImageCapture.setTargetRotation(). For apps that don't need custom rotation logic, this removes the lifecycle management overhead.
From alpha01 (March 2026), CameraController.setSessionConfig() also landed — it lets you inject a custom SessionConfig for advanced use cases that CameraController's higher-level API doesn't expose directly. When a custom session config is active, other CameraController configuration methods are disabled to prevent conflicts. This is the escape hatch for teams that want CameraController's lifecycle management but need direct session configuration access.
Should You Use This Now?
Alpha APIs carry the usual warning: shapes can change before stable. CameraX alpha releases have historically been fairly stable by the time they reach beta, but "historically" isn't a guarantee. Here's how I'd think about adopting each piece:
- Viewfinder gestures + FocusState — prototype immediately if you're building a new camera screen. The API surface is small and well-bounded, and even if parameter names shift, the migration will be mechanical.
- Night Mode Indicator — easy to adopt defensively behind
isNightModeIndicatorSupported(). The worst case if it changes is a one-line update to the constant names. - GPU ImageAnalysis (PRIVATE format) — adopt if you're already building GPU-based processing. If you're not, there's no urgency; this doesn't replace the CPU path, it adds an alternative.
- Audio controls on Recorder — safe to adopt; these are additive builder parameters with straightforward fallback behavior if the device doesn't support the requested spec.
- AE/AWB locking — useful for continuous video autofocus scenarios. The mode enum may expand before stable but existing modes will be kept.
- Concurrent camera styling — alpha cosmetics are the highest risk for API churn. Wait for beta before shipping this in production.
Dependency: add 1.7.0-alpha02 to your libs.versions.toml or BOM if you want to experiment. The stable version stays at 1.6.1 for production — alpha02 and stable are independent version tracks and won't conflict if you test on a feature branch.
The broader theme across this alpha is that CameraX is absorbing the boilerplate layer that every camera app maintains independently. Gestures, focus state observation, night mode signals, GPU pipeline access, audio config — each of these has an existing custom implementation in almost every non-trivial camera codebase. Moving them into the library reduces per-app maintenance surface and creates consistent behavior across device variety. That's exactly what a platform abstraction layer should do, and it's taken CameraX a few years to get here. The alpha02 shape looks right.
No comments yet. Be the first to leave one!