如何将Camera2 API设为标准相机?Camera2 API竖屏图片显示问题
Hey there, let's break down your two Camera2-related questions and solve them step by step!
First off, let's clarify: when we talk about the "standard camera" on Android, we're referring to the system's default camera app. If you want to build your own camera app using Camera2 API and set it as the system's default camera, here's what you need to do:
Declare required permissions: You'll need the
CAMERApermission (mandatory for camera access). For Android 10+, if you're saving photos to public storage, addWRITE_EXTERNAL_STORAGE(or use MediaStore for scoped storage instead). Don't forget to request runtime permissions for these as well!Add Intent Filters to your camera Activity: This lets the system recognize your app as a valid camera option. Add these filters in your
AndroidManifest.xml:
<activity android:name=".YourCameraActivity"> <!-- For image capture --> <intent-filter> <action android:name="android.media.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <!-- For video capture (optional) --> <intent-filter> <action android:name="android.media.action.VIDEO_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
- Handle incoming camera requests: Make sure your Activity can process the intent data passed from other apps (like the output Uri for saving photos). Once your app meets these requirements, users can go to system settings and select your app as the default camera.
This is a super common issue with Camera2 API, and it boils down to image orientation metadata (Exif) not being handled properly or incorrect output configuration during capture. Let's cover two reliable fixes:
Fix 1: Rotate the Bitmap using Exif data when displaying
When you decode the image with BitmapFactory, it doesn't automatically apply the orientation stored in the image's Exif data. Here's how to fix that:
fun getRotatedBitmap(filePath: String): Bitmap? { // Get Exif orientation info val exif = ExifInterface(filePath) val orientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL ) // Decode the original bitmap val originalBitmap = BitmapFactory.decodeFile(filePath) ?: return null // Rotate the bitmap based on Exif orientation return when (orientation) { ExifInterface.ORIENTATION_ROTATE_90 -> rotateBitmap(originalBitmap, 90f) ExifInterface.ORIENTATION_ROTATE_180 -> rotateBitmap(originalBitmap, 180f) ExifInterface.ORIENTATION_ROTATE_270 -> rotateBitmap(originalBitmap, 270f) else -> originalBitmap } } private fun rotateBitmap(bitmap: Bitmap, degrees: Float): Bitmap { val matrix = Matrix() matrix.postRotate(degrees) return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) }
Then use this getRotatedBitmap method instead of directly decoding the file, and set the returned bitmap to your ImageView.
Fix 2: Configure Camera2 to capture in portrait orientation directly
You can adjust the Camera2 capture setup to output portrait images natively. Modify the Camera2Basic sample code like this:
- Adjust ImageReader dimensions for portrait:
// Get device display rotation val rotation = windowManager.defaultDisplay.rotation val displaySize = Point() windowManager.defaultDisplay.getSize(displaySize) // Swap width/height based on rotation to match portrait val outputWidth = if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) { displaySize.height } else { displaySize.width } val outputHeight = if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) { displaySize.width } else { displaySize.height } // Create ImageReader with adjusted dimensions mImageReader = ImageReader.newInstance(outputWidth, outputHeight, ImageFormat.JPEG, 2)
- Set JPEG orientation in CaptureRequest:
val captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE) captureBuilder.addTarget(mImageReader.surface) // Calculate and set correct JPEG orientation val characteristics = cameraManager.getCameraCharacteristics(mCameraId) captureBuilder.set( CaptureRequest.JPEG_ORIENTATION, getJpegOrientation(rotation, characteristics) )
- Add the orientation calculation helper method:
private fun getJpegOrientation(displayRotation: Int, characteristics: CameraCharacteristics): Int { val sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!! return when (displayRotation) { Surface.ROTATION_0 -> sensorOrientation Surface.ROTATION_90 -> (sensorOrientation + 270) % 360 Surface.ROTATION_180 -> (sensorOrientation + 180) % 360 Surface.ROTATION_270 -> (sensorOrientation + 90) % 360 else -> sensorOrientation } }
This way, the captured image will already be in the correct portrait orientation, no extra rotation needed when displaying.
内容的提问来源于stack exchange,提问作者D T




