这个需求说起来挺奇葩,为什么这么讲,因为Camera2本来就是用来拍照录像,就只因为当前系统预置应用 Camera2 在录像的时候,很容易出现各种奇怪问题,还不好定位并解决,然后产品说:把Camera2 里面的录像功能给屏蔽了吧。胳膊拧不过大腿,改吧。
需要修改
folder\packages\apps\Camera2\src\com\android\camera\app\ModuleManagerImpl.java
首先找到 ModuleManagerImpl.java 的 registerModule()方法,这个方法是注册并找到当前Camera2所有支持的模块。其实当时通过打印日志,除了打印出来 PhotoModule 和 VideoModule,我也没发现其他什么第三个模块。处理方式也很简单,当识别到了注册加载的模块是视频模块时,就不去加载。
在这个方法中修改:
@Override
public void registerModule(ModuleAgent agent) {
if (agent == null) {
throw new NullPointerException("Registering a null ModuleAgent.");
}
final int moduleId = agent.getModuleId();
if (moduleId == MODULE_INDEX_NONE) {
throw new IllegalArgumentException(
"ModuleManager: The module ID can not be " + "MODULE_INDEX_NONE");
}
if (mRegisteredModuleAgents.get(moduleId) != null) {
throw new IllegalArgumentException("Module ID is registered already:" + moduleId);
}
//关键代码
//Hide Video Module from Camera2 app.
if (hideVideoModule(agent)) {
Log.w(TAG,"Hide Video Module from Camera2 app,agent is -> " + agent + ", moduleId is -> " +
agent.getModuleId() + ",Scope Names pace -> " + agent.getScopeNamespace());
}else{
mRegisteredModuleAgents.put(moduleId, agent);
}
}
/**
* Hide Video Module from Camera2 app.
* @return true hide
* false show
*/
private boolean hideVideoModule(ModuleAgent agent){
boolean needHide = false;
String videoModuleName = "VideoModule";
if (agent!= null && !TextUtils.isEmpty(agent.getScopeNamespace()) &&
videoModuleName.contains(agent.getScopeNamespace())){
needHide = true;
}
return needHide;
}
就是上面这些东西了。
看一下修改之前和修改之后:
![](https://i-blog.csdnimg.cn/blog_migrate/a89c43182c2b91741047f9c0d10249b8.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/ba0d56fe2040a399e0ab4852ed1a6dc2.png)
当这样操作完了,还不放心,害怕当使用adb 启动相机的时候会 crash,后来测试了一下,没有发生 crash 的现象。测试的时候使用下面命令开启摄像头:
adb shell am start -W com.android.camera2/com.android.camera.CameraActivity
以上就是(基于 Android 8.1.0)屏蔽 Camera2 应用中录像按钮的全部内容。
------------------------------------- 分割线 -------------------------------------
等有时间把怎么定位修改哪里的步骤补充一下。
补充:
一般这种修改系统原生应用相关界面的任务,先使用一些方法定位当前界面相关信息。定位的时候两种方法:
【方法一】获取当前界面的所有 id(在 window_dump.xml 中查找 :id)
adb shell uiautomator dump
adb pull /sdcard/window_dump.xml .
【方法二】获取当前界面是哪一个界面(在 current_stack_info.txt 中查找 Hist #0)
adb shell dumpsys activity activities > current_stack_info.txt
通过方法二知道了这个相关界面是 com.android.camera.CameraActivity,找到com.android.camera.CameraActivity.java 源码,分析生命周期中的方法,在 onCreateTasks(Bundle state)方法中定位到了和模式选择相关的代码:
mModeListView = (ModeListView) findViewById(R.id.mode_list_layout);
mModeListView.init(mModuleManager.getSupportedModeIndexList());
通过这个 mModeListView.init() 方法知道我们猜测只需要在调用 init()方法的时候,把视频相关给过滤掉就可以了。所以问题来到了 mModuleManager.getSupportedModeIndexList() 方法,在调用这个方法获取 ModuleManager 所支持的 ModeIndexList 的时候,把视频给过滤掉。然后一步步定位,打印日志确定需要过滤的信息,最终找到正确位置。
其实当在处理这个问题的时候,并不是一下就能找到关键代码的,方法二走下来,走不通了,就又沿着方法一走,然后两头往中间走,最终走通。
记录一下,刚开始跟源码不多久,觉得越来越有成就感。
另外,处理这个问题的方式你有其他方法吗,评论区留言讨论一下吧~