You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 4.x中闪光灯相关代码触发java.lang.VerifyError问题求助

问题分析与修复方案

这个问题我之前也碰到过,本质是Android低版本设备的类加载验证机制在作祟,咱们一步步拆解:

一、问题根源

Android 4.1-4.3对应API 16-18,而CameraManager、CameraAccessException这些类是API 23才新增的。虽然你用Build.VERSION.SDK_INT >=23做了条件判断,但Java的类加载规则是:类在初始化阶段会解析所有引用的类——也就是说,当你的FlashOnClickListener内部类被加载时,系统会尝试查找它里面提到的所有类,低版本系统找不到CameraManager,直接触发java.lang.VerifyError,甚至还没走到条件判断代码就崩了。

你提到的PackageManager.hasSystemFeature(...)触发错误,大概率也是因为这段代码所在的类间接引用了高版本API类,导致类加载失败。

二、修复方案

核心思路是把高版本API相关代码完全隔离,避免低版本设备加载到不存在的类,这里提供两种可靠的实现方式:

方案1:拆分高版本代码到独立类

创建一个只在API 23+环境下使用的工具类,只有满足版本条件时才去加载它:

// 仅API 23+可用的闪光灯处理类
public class FlashHandlerApi23 {
    public static void turnOnFlash(Context context, ImageView theFlash) {
        try {
            CameraManager camManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            if (camManager != null) {
                String[] cameraIds = camManager.getCameraIdList();
                if (cameraIds.length > 0) {
                    camManager.setTorchMode(cameraIds[0], true);
                    theFlash.setImageResource(R.drawable.ic_highlight_black_24dp);
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
}

然后修改你的内部类逻辑:

flashBtnListener = new FlashOnClickListener();

class FlashOnClickListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        if(Build.VERSION.SDK_INT >= 23) {
            // 只有高版本才会加载FlashHandlerApi23,低版本不会走到这里
            FlashHandlerApi23.turnOnFlash(mContext, theFlash);
        } else {
            // 原有低版本闪光灯逻辑保持不变
            try {
                mCamera = Camera.open();
                Camera.Parameters parameters = mCamera.getParameters();
                List<String> flashModes = parameters.getSupportedFlashModes();
                if (flashModes != null && flashModes.contains(android.hardware.Camera.Parameters.FLASH_MODE_TORCH)) {
                    parameters.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_TORCH);
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();
                    theFlash.setImageResource(R.drawable.ic_highlight_black_24dp);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

方案2:使用反射调用高版本API

如果不想拆分类,可以用反射动态调用CameraManager的方法,避免直接引用类:

class FlashOnClickListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        if(Build.VERSION.SDK_INT >= 23) {
            try {
                // 反射获取CameraManager类
                Class<?> cameraManagerClass = Class.forName("android.hardware.camera2.CameraManager");
                Object camManager = mContext.getSystemService(Context.CAMERA_SERVICE);
                
                if (camManager != null) {
                    // 反射调用getCameraIdList方法
                    Method getCameraIdListMethod = cameraManagerClass.getMethod("getCameraIdList");
                    String[] cameraIds = (String[]) getCameraIdListMethod.invoke(camManager);
                    
                    if (cameraIds.length > 0) {
                        // 反射调用setTorchMode方法
                        Method setTorchModeMethod = cameraManagerClass.getMethod("setTorchMode", String.class, boolean.class);
                        setTorchModeMethod.invoke(camManager, cameraIds[0], true);
                        theFlash.setImageResource(R.drawable.ic_highlight_black_24dp);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // 原有低版本闪光灯逻辑保持不变
            try {
                mCamera = Camera.open();
                Camera.Parameters parameters = mCamera.getParameters();
                List<String> flashModes = parameters.getSupportedFlashModes();
                if (flashModes != null && flashModes.contains(android.hardware.Camera.Parameters.FLASH_MODE_TORCH)) {
                    parameters.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_TORCH);
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();
                    theFlash.setImageResource(R.drawable.ic_highlight_black_24dp);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

三、额外注意事项

  • 你的Manifest配置没问题,required="false"确保应用能在无闪光灯设备上安装,无需修改;
  • 低版本的Camera使用后记得在onPause等生命周期方法中释放资源,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:41:54