Android系统相机应用支持三个相机切换功能实现
需求背景
平板电脑,硬件上接通了三个摄像头(后摄:0,前摄:1,微距:2),需要通过修改原生摄像头应用实现三个镜头的自由切换。
原生相机运行抛出异常
private static int getNextSupportedVideoQualityIndex(int cameraId, int start) {
for (int i = start + 1; i < sVideoQualities.length; ++i) {
if (isVideoQualitySupported(sVideoQualities[i])
&& CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])) {
// We found a new supported quality.
return i;
}
}
// Failed to find another supported quality.
if (start < 0 || start >= sVideoQualities.length) {
// This means we couldn't find any supported quality.
throw new IllegalArgumentException("Could not find supported video qualities.");
}
// We previously found a larger supported size. In this edge case, just
// return the same index as the previous size.
return start;
}
分析源码发现CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])一直返回false,通过追踪打印发现系统底层只有配置摄像头Id 0跟1的视频质量文件,但是上层传入顺序为0,2导致找不到匹配的视频质量,修改前后摄微距三个摄像头的排序问题解决(后摄:0,前摄:1,微距:2)
实现思路
1:原生相机UI修改
找到原生相机切换按钮图标控制类ButtonManager.java,分析发现按钮初始化方法initializeButton,initializeCameraButton,查看initializeCameraButton
case BUTTON_CAMERA:
initializeCameraButton(button, cb, preCb, R.array.camera_id_icons);
break;
<array name="camera_id_icons" translatable="false">
<item>@drawable/ic_switch_camera_back</item>
<item>@drawable/ic_switch_camera_front</item>
<item>@drawable/ic_switch_gcam</item>
</array>
只有前摄后摄的切换选项图片,新增一个微距的切换item选项
2:按钮事件分析
运行之后发现前后摄切换没有问题,但是切换到第三个选项的时候,也只是切换了后摄,追踪点击事件,发现这里切换相机的时候确实是传入cameraid==2
button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() {
@Override
public void stateChanged(View view, int state) {
mSettingsManager.setValueByIndex(mAppController.getModuleScope(),
Keys.KEY_CAMERA_ID, state);
int cameraId = mSettingsManager.getInteger(mAppController.getModuleScope(),
Keys.KEY_CAMERA_ID);
// This is a quick fix for ISE in Gcam module which can be
// found by rapid pressing camera switch button. The assumption
// here is that each time this button is clicked, the listener
// will do something and then enable this button again.
button.setEnabled(false);
if (cb != null) {
cb.onStateChanged(cameraId);