在Andoird JB 4.2中,Camera的代码有很是大的变更,无论是frameworks,仍是APP。逻辑更加严谨,google里的程序员真的很喜欢用设计模式,处处均可以看到设计模式的影子,刚刚拿到JB4.2源码的时候,我被绕晕了,一方面是代码变化太大,另外一个最主要的因素仍是本身功力不够。 java
如今,咱们讨论一下如何在JB 4.2的Camera中实现一个功能:添加一个开关来控制拍照声音。 android
在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文件中,以下代码: app
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方法, ide
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的改动很大,不过改动起来仍是很方便的。 google
在UI方面,由于要在CameraSettings中添加一个开关,则须要作以下操做: 设计
packages/apps/Camera/src/com/android/camera/SettingsChecker.java code
... 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 咱们均可以控制了。其可扩展性确实挺高的,可是容易让人绕晕。