当前位置: 首页 > news >正文

JB4.2:添加一个SwithButton控制ShutterSound

为什么80%的码农都做不了架构师?>>>   hot3.png

在Andoird JB 4.2中,Camera的代码有非常大的变动,不管是frameworks,还是APP。逻辑更加严谨,google里的程序员真的很喜欢用设计模式,到处都可以看到设计模式的影子,刚刚拿到JB4.2源码的时候,我被绕晕了,一方面是代码变化太大,另一个最主要的因素还是自己功力不够。

现在,我们讨论一下如何在JB 4.2的Camera中实现一个功能:添加一个开关来控制拍照声音。

在4.2中实现应该说是更加简单了,因为系统在frameworks已经提供了一个方法:enableShutterSound(boolean enabled),其实我们可以在上层直接调用该方法来控制shutterSound,但是实践证明,它只能控制拍照的声音,而录制的声音会失效。

我们先跟踪一下这个方法,enableShutterSound(boolean enabled)方法在frameworks/base/core/java/android/hardware/Camera.java中,

public final boolean enableShutterSound(boolean enabled) {
...
    return _enableShutterSound(enabled);
}

private native final boolean _enableShutterSound(boolean enabled);
在这里,它调用了一个native方法_enableShutterSound(boolean enabled),查看JNI目录,在

frameworks/base/core/jni/android_hardware_Camera.cpp文件中,如下代码:

static JNINativeMethod camMethods[] = {
    ...
    {"_enableShutterSound","(Z)Z",(void *)anroid_hardware_Camera_enableShutterSound},
    ...
}
然后我们分析
android_hardware_Camera_enableShutterSound()
如下:
static jboolean android_hardware_Camera_enableShutterSound(JNIEnv *env, jobject thiz, jboolean enabled) {
     ...
     status_t rc = camera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, value, 0);
     ...
}
然后转到frameworks/av/services/camera/libcameraservice/CameraClient.cpp。从4.1开始,Camera被更加重视了,将av放到base同等级别的目录下,呵呵。
status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
    ...
    }else if(cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
        switch(arg1) {
            case 0:
                return enableShutterSound(false);
            case 1:
                return enableShutterSound(true);
            default:
                return BAD_VALUE;
        }
        return OK;
    }
    ...
}

跟踪enableShutterSound方法,

status_t CameraClient::enableShutterSound(bool enable) {
    ...

    if (enable){
        mPlayShutterSound = true;
        return OK;
    }
    ...
    mPlayShutterSound = false;
    return false;
}
在snapshot taken callback,即
void CameraCilent::handleShutter(void) {
    if(mPlayShutterSound) {
         mCameraService->playSound(CameraService::SOUND_SHUTTER);
    }
    ...
}
 而在,录制视频的动作中,
status_t CameraCilent::startRecordingMode(){
    ...
    mCameraService->playSound(CameraService::SOUND_RECORDING);
    ...
}

void CameraCilent::stopRecording(){
    ...
    mCameraService->playSound(CameraService::SOUND_RECORDING);
    ...
}
因此,framework/base/core/java/android/hardware/Camera中的enableShutterSound对Recording没有作用,因此我们只需加入与拍照时的同等逻辑,即:
status_t CameraCilent::startRecordingMode(){
    ...
    if (mPlayShutterSound) {
        mCameraService->playSound(CameraService::SOUND_RECORDING);
    }
    ...
}

void CameraCilent::stopRecording(){
    ...
    if (mPlayShutterSound) {
        mCameraService->playSound(CameraService::SOUND_RECORDING);
    }
    ...
}
这样我们就可以直接在上层调用android.hardware.Camera中的enableShutterSound来控制拍照和录制模式的shutter sound.

下面实现app层的逻辑,正如我前面所说的那样,4.2的改动很大,不过改动起来还是很方便的。

在UI方面,因为要在CameraSettings中添加一个开关,则需要做如下操作:

packages/apps/Camera/src/com/android/camera/SettingsChecker.java

...
public static final int ROW_SETTING_SHUTTER_SOUND = 51;
...

public static final int[] SETTING_GROUP_COMMON_FOR_TAB_MY_SETTING = new int[]{
...
   ROW_SETTING_SHUTTER_SOUND;
...
}

public static final int[] SETTING_GROUP_COMMON_FOR_TAB = new int[]{
...
   ROW_SETTING_SHUTTER_SOUND;
...
}

public static final int[] SETTING_GROUP_CAMERA_FOR_PARAMETERS = new int[]{
...
   ROW_SETTING_SHUTTER_SOUND;
...
}

public static final int[] SETTING_GROUP_VIDEO_FOR_PARAMETERS = new int[]{
...
   ROW_SETTING_SHUTTER_SOUND;
...
}

public static final int[] SETTING_GROUP_ALL_IN_SETTING = new int[]{
...
   ROW_SETTING_SHUTTER_SOUND;
...
}

static {
...
MATRIX_MODE_STATE[ROW_SETTING_SHUTTER_SOUND] = new int[]{STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO,STATE_EO};
...

RESET_STATE_VALUE[ROW_SETTING_SHUTTER_SOUND] = new String[]{"on"};
...

KEYS_FOR_SETTING[ROW_SETTING_SHUTTER_SOUND] = CameraSettings.KEY_SOUND;
...

MATRIX_SETTING_VISIBLE[CAMERA_BACK_ID][ROW_SETTING_SHUTTER_SOUND] = true;
...

MATRIX_SETTING_VISIBLE[CAMERA_FRONT_ID][ROW_SETTING_SHUTTER_SOUND] = true;
...

DEFAULT_VALUE_FOR_SETTING_ID[ROW_SETTING_SHUTTER_SOUND] = R.string.pref_camera_shuttersound_default;
...

}


private static String getParameterValue(Parameters parameters, int row) {
...
   case ROW_SETTING_SHUTTER_SOUND:
        throw new CameraSettingsException("Cannot get sound from parameters"); 
...

}  


private static boolean setParameterValue(Context context, Parameters parameters, int row, String Value) {
    ...
    case ROW_SETTING_SHUTTER_SOUND:
        updateShutterSound(context);
        break;
    ...
}


private static boolean isParamenterSupportedValue(Paramenters parameters, int row, String value) {
   ...
    case ROW_SETTING_SHUTTER_SOUND:
        support = true;
        break;
   ...
}

private static void updateShutterSound(Context context) {
    Camera camera = (Camera) context;
    camera.updateShutterSound();
}

packages/apps/Camera/src/com/android/camera/Camera.java

public static final int MSG_SHUTTER_SOUND_KEY = 24;

...

public void updateShutterSound() {
    mMainHandler.sendEmptyMessage(MSG_SHUTTER_SOUND_KEY);
}

...

public Handler mMainHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        ...
            case MSG_SHUTTER_SOUND_KEY:
                if ("on".equals(mSettingChecker.getStringCurrentValue(SettingChecker.ROW_SETTING_SHUTTER_SOUND))) {
                 mCameraActor.enableShutterSound(true);
             } else {
                 mCameraActor.enableShutterSound(false);
             }
        ...
    }

}

public void enableShutterSound(boolean enable) {
    mCameraDevice.enableShutterSound(enable);
}

packages/apps/Camera/src/com/android/camera/CameraManager.java

private static final int SET_SHUTTER_SOUND = 118;

public void enableShutterSound(boolean enable) {
    mSig.close();
    mCameraHandler.obtainMessage(SET_SHUTTER_SOUND,enable).sendToTarget();
    mSig.block();
}

private class CameraHandler extends Handler {
    ...
    @Override
    public void handleMessage(final Message msg) {
    ...
        case SET_SHUTTER_SOUND:
            mCamera.enableShutterSound((Boolean)msg.obj);
            break;
    ...
  
    }
    ...
}
packages/apps/Camera/src/com/mediatek/camera/ICamera.java
public interface ICamera {
    ...
    public void enableShutterSound(boolean enable);
    ...
}
packages/apps/Camera/src/com/mediatek/camera/AndroidCamera.java
...
import android.hardware.Camera;
...

public class AndroidCamera implements ICamera {
    ...
    protect Camera mCamera;
    ...
    public void enableShutterSound(boolean enable) {
        mCamera.enableShutterSound(enable);
    }
    ...
}

packages/apps/Camera/src/com/android/camera/actor/CameraActor.java

public void enableShutterSound(boolean enable) {
    mContext.enableShutterSound(enable);
}

从上面代码可以看出,AndroidCamera.java中的enableShutterSound方法调用了framework层android.hardware.Camera.enableShutterSound;而在Camera中,

case MSG_SHUTTER_SOUND_KEY:
                if ("on".equals(mSettingChecker.getStringCurrentValue(SettingChecker.ROW_SETTING_SHUTTER_SOUND))) {
                 mCameraActor.enableShutterSound(true);
             } else {
                 mCameraActor.enableShutterSound(false);
             }

在这里,只需简单的调用mCameraActor.enableShutterSound即可,而其他的Actor都是继承自CameraActor,也就是说,我们只需加上上述代码,其他各种模式的shutter sound 我们都可以控制了。其可扩展性确实挺高的,但是容易让人绕晕。


转载于:https://my.oschina.net/jerikc/blog/113015

相关文章:

  • Linux下取本机所有网口的ip地址
  • android 蓝牙源码分析
  • 新版本的GNS3(0.8.2)模拟ASA的教程
  • LVM的综合性介绍及实现
  • (实战篇)如何缓存数据
  • android 抓包分析
  • 从外形如何分辨iTouch是几代的?
  • Word中使用正则表达式进行查找和替换
  • 打开Windows2008 R2 Server Manager或执行Windows Update时出现0x800F0818错误
  • 针对11.2 RAC丢失OCR和Votedisk所在ASM Diskgroup的恢复手段
  • Linux 获取CPU温度
  • OpenCV第五章练习p163_5~8
  • 用gdbserver调试共享库(二)
  • java类型通配符
  • 用jQuery实现一些导航条切换,显示隐藏
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • CEF与代理
  • CSS 专业技巧
  • ESLint简单操作
  • javascript 哈希表
  • JavaScript设计模式与开发实践系列之策略模式
  • Java反射-动态类加载和重新加载
  • JS函数式编程 数组部分风格 ES6版
  • MaxCompute访问TableStore(OTS) 数据
  • python docx文档转html页面
  • Python打包系统简单入门
  • Redux 中间件分析
  • use Google search engine
  • 大快搜索数据爬虫技术实例安装教学篇
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 温故知新之javascript面向对象
  • 新手搭建网站的主要流程
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 【干货分享】dos命令大全
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十八)SpringBoot之发送QQ邮件
  • (转)shell调试方法
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net6 Api Swagger配置
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • @Not - Empty-Null-Blank
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [ 数据结构 - C++]红黑树RBTree
  • [<事务专题>]
  • [APIO2015]巴厘岛的雕塑
  • [C#]C# OpenVINO部署yolov8图像分类模型
  • [C++随笔录] 红黑树
  • [CareerCup] 2.1 Remove Duplicates from Unsorted List 移除无序链表中的重复项
  • [Flutter] extends、implements、mixin和 abstract、extension的使用介绍说明
  • [hive] posexplode函数