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

在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 咱們均可以控制了。其可擴展性確實挺高的,可是容易讓人繞暈。

相關文章
相關標籤/搜索