66
77package cn .nodemedia ;
88
9- import android .annotation .SuppressLint ;
109import android .content .Context ;
1110import android .graphics .Rect ;
1211import android .graphics .SurfaceTexture ;
1716import android .hardware .camera2 .CameraManager ;
1817import android .hardware .camera2 .CaptureRequest ;
1918import android .hardware .camera2 .params .MeteringRectangle ;
19+ import android .hardware .camera2 .params .OutputConfiguration ;
20+ import android .hardware .camera2 .params .SessionConfiguration ;
2021import android .hardware .camera2 .params .StreamConfigurationMap ;
22+ import android .os .Build ;
2123import android .os .Handler ;
2224import android .os .HandlerThread ;
2325import android .util .Log ;
2426import android .util .Size ;
2527import android .view .Surface ;
26- import java .util .Arrays ;
28+ import java .util .ArrayList ;
29+ import java .util .List ;
30+ import java .util .concurrent .Executors ;
2731
2832public class Camera2Manager {
2933 private static final String TAG = "Camera2Manager" ;
@@ -35,12 +39,10 @@ public class Camera2Manager {
3539 private HandlerThread backgroundThread ;
3640 private Handler backgroundHandler ;
3741
38- private String cameraId ;
3942 private SurfaceTexture surfaceTexture ;
4043 private Size previewSize ;
4144 private CameraCharacteristics cameraCharacteristics ;
4245 private float currentZoomRatio = 1.0f ;
43- private boolean isTorchOn = false ;
4446
4547 public interface CameraStateListener {
4648 void onCameraOpened ();
@@ -59,7 +61,6 @@ public void setCameraStateListener(CameraStateListener listener) {
5961 this .stateListener = listener ;
6062 }
6163
62- @ SuppressLint ("MissingPermission" )
6364 public void openCamera (int facingId , SurfaceTexture surfaceTexture , int width , int height ) {
6465 this .surfaceTexture = surfaceTexture ;
6566
@@ -87,7 +88,7 @@ public void openCamera(int facingId, SurfaceTexture surfaceTexture, int width, i
8788 surfaceTexture .setDefaultBufferSize (previewSize .getWidth (), previewSize .getHeight ());
8889 }
8990
90- cameraManager .openCamera (cameraId , stateCallback , backgroundHandler );
91+ cameraManager .openCamera (cameraId , deviceStateCallback , backgroundHandler );
9192
9293 } catch (CameraAccessException e ) {
9394 Log .e (TAG , "无法访问摄像头: " + e .getMessage ());
@@ -114,10 +115,6 @@ public void closeCamera() {
114115 stopBackgroundThread ();
115116 }
116117
117- public boolean isFrontCamera () {
118- return true ;
119- }
120-
121118 public Size getPreviewSize () {
122119 return previewSize ;
123120 }
@@ -191,9 +188,22 @@ private void createCameraPreviewSession() {
191188
192189 previewRequestBuilder = cameraDevice .createCaptureRequest (CameraDevice .TEMPLATE_PREVIEW );
193190 previewRequestBuilder .addTarget (surface );
194-
195- cameraDevice .createCaptureSession (Arrays .asList (surface ), sessionStateCallback , backgroundHandler );
196-
191+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .R ) {
192+ // 使用 SessionConfiguration
193+ ArrayList <OutputConfiguration > outputConfigurations = new ArrayList <>();
194+ OutputConfiguration configuration = new OutputConfiguration (surface );
195+ outputConfigurations .add (configuration );
196+ SessionConfiguration sessionConfig = new SessionConfiguration (
197+ SessionConfiguration .SESSION_REGULAR , // 或 SESSION_HIGH_SPEED 等
198+ outputConfigurations ,
199+ Executors .newCachedThreadPool (), // Executor(用于回调)
200+ sessionStateCallback
201+ );
202+ cameraDevice .createCaptureSession (sessionConfig );
203+ } else {
204+ // 使用旧方法(带 Handler)
205+ cameraDevice .createCaptureSession (List .of (surface ), sessionStateCallback , backgroundHandler );
206+ }
197207 } catch (CameraAccessException e ) {
198208 Log .e (TAG , "创建预览会话失败: " + e .getMessage ());
199209 if (stateListener != null ) {
@@ -218,16 +228,16 @@ public void startPreview() {
218228 }
219229 }
220230
221- private final CameraDevice .StateCallback stateCallback = new CameraDevice .StateCallback () {
231+ private final CameraDevice .StateCallback deviceStateCallback = new CameraDevice .StateCallback () {
222232 @ Override
223- public void onOpened (@ SuppressLint ( "InvalidAccessToGuardedMember" ) CameraDevice camera ) {
233+ public void onOpened (CameraDevice camera ) {
224234 Log .d (TAG , "摄像头已打开" );
225235 cameraDevice = camera ;
226236 createCameraPreviewSession ();
227237 }
228238
229239 @ Override
230- public void onDisconnected (@ SuppressLint ( "InvalidAccessToGuardedMember" ) CameraDevice camera ) {
240+ public void onDisconnected (CameraDevice camera ) {
231241 Log .d (TAG , "摄像头已断开连接" );
232242 camera .close ();
233243 cameraDevice = null ;
@@ -237,7 +247,7 @@ public void onDisconnected(@SuppressLint("InvalidAccessToGuardedMember") CameraD
237247 }
238248
239249 @ Override
240- public void onError (@ SuppressLint ( "InvalidAccessToGuardedMember" ) CameraDevice camera , int error ) {
250+ public void onError (CameraDevice camera , int error ) {
241251 Log .e (TAG , "摄像头错误: " + error );
242252 camera .close ();
243253 cameraDevice = null ;
@@ -249,7 +259,7 @@ public void onError(@SuppressLint("InvalidAccessToGuardedMember") CameraDevice c
249259
250260 private final CameraCaptureSession .StateCallback sessionStateCallback = new CameraCaptureSession .StateCallback () {
251261 @ Override
252- public void onConfigured (@ SuppressLint ( "InvalidAccessToGuardedMember" ) CameraCaptureSession session ) {
262+ public void onConfigured (CameraCaptureSession session ) {
253263 Log .d (TAG , "摄像头会话已配置" );
254264 captureSession = session ;
255265 startPreview ();
@@ -259,7 +269,7 @@ public void onConfigured(@SuppressLint("InvalidAccessToGuardedMember") CameraCap
259269 }
260270
261271 @ Override
262- public void onConfigureFailed (@ SuppressLint ( "InvalidAccessToGuardedMember" ) CameraCaptureSession session ) {
272+ public void onConfigureFailed (CameraCaptureSession session ) {
263273 Log .e (TAG , "摄像头会话配置失败" );
264274 if (stateListener != null ) {
265275 stateListener .onCameraError ("摄像头会话配置失败" );
@@ -296,30 +306,45 @@ public float getMaxZoomRatio() {
296306 }
297307
298308 /**
299- * 获取当前变焦比例
309+ * 获取当前变焦比例(绝对值)
300310 */
301311 public float getZoomRatio () {
302312 return currentZoomRatio ;
303313 }
304314
305315 /**
306- * 设置变焦比例
316+ * 获取当前归一化变焦值 (0.0-1.0)
317+ */
318+ public float getNormalizedZoom () {
319+ float maxZoom = getMaxZoomRatio ();
320+ float minZoom = getMinZoomRatio ();
321+ if (maxZoom <= minZoom ) {
322+ return 0.0f ;
323+ }
324+ return (currentZoomRatio - minZoom ) / (maxZoom - minZoom );
325+ }
326+
327+ /**
328+ * 设置归一化变焦值
329+ * @param normalizedRatio 归一化值,0.0 对应 minZoom,1.0 对应 maxZoom
307330 */
308- public void setZoomRatio (float ratio ) {
331+ public void setZoomRatio (float normalizedRatio ) {
309332 if (cameraCharacteristics == null || previewRequestBuilder == null ) {
310333 return ;
311334 }
312335
313336 float maxZoom = getMaxZoomRatio ();
314337 float minZoom = getMinZoomRatio ();
315338
316- if (ratio < minZoom ) {
317- ratio = minZoom ;
318- } else if (ratio > maxZoom ) {
319- ratio = maxZoom ;
339+ // 限制归一化值在 0.0-1.0 范围内
340+ if (normalizedRatio < 0.0f ) {
341+ normalizedRatio = 0.0f ;
342+ } else if (normalizedRatio > 1.0f ) {
343+ normalizedRatio = 1.0f ;
320344 }
321345
322- currentZoomRatio = ratio ;
346+ // 将归一化值转换为实际的变焦比例
347+ currentZoomRatio = minZoom + normalizedRatio * (maxZoom - minZoom );
323348
324349 try {
325350 // 计算变焦区域
@@ -369,14 +394,17 @@ public void enableTorch(boolean enable) {
369394 return ;
370395 }
371396
372- isTorchOn = enable ;
373397 Log .d (TAG , "设置闪光灯: " + (enable ? "开启" : "关闭" ));
374398
375399 try {
376400 // 设置闪光灯模式
377401 if (enable ) {
402+ // 开启 TORCH 时需要将 AE_MODE 设置为 ON,避免 AUTO_FLASH 覆盖 TORCH 设置
403+ previewRequestBuilder .set (CaptureRequest .CONTROL_AE_MODE , CaptureRequest .CONTROL_AE_MODE_ON );
378404 previewRequestBuilder .set (CaptureRequest .FLASH_MODE , CaptureRequest .FLASH_MODE_TORCH );
379405 } else {
406+ // 关闭 TORCH 时恢复 AUTO_FLASH 模式
407+ previewRequestBuilder .set (CaptureRequest .CONTROL_AE_MODE , CaptureRequest .CONTROL_AE_MODE_ON_AUTO_FLASH );
380408 previewRequestBuilder .set (CaptureRequest .FLASH_MODE , CaptureRequest .FLASH_MODE_OFF );
381409 }
382410
0 commit comments