安卓手机如何关闭相机快门声?

12

我正在使用:

camera.takePicture(null, rawCallback, jpegCallback);

但是在某些设备上,当相机捕捉图像时会发出声音。

请问有没有人能帮忙,如何将相机快门声静音?


我认为这有点难以实现。至少在美国,法律规定所有相机设备都要发出快门声。据我所知,在一些其他国家也是如此。 - harism
在某些设备上,Harism会导致问题。我已经在Nexus、S2和Nexus平板电脑上进行了测试,所有设备都能够静默捕获,但HTC Desicer和一些设备会出现问题。 - PankajAndroid
将一个静音声音文件作为输入参数传递给该方法,这个想法可行吗? - dumbfingers
5个回答

12

为了将声音静音,请在捕获图像之前放置以下代码

 AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
 mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);
 camera.takePicture(null, rawCallback, jpegCallback);

在1秒后,通过使用以下代码取消静音:

 final Handler handler = new Handler();
 Timer t = new Timer();
 t.schedule(new TimerTask() {
    public void run() {
        handler.post(new Runnable() {
            public void run() {
            AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
            mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false);
                    }
                });
            }
    }, 1000); 

1
为什么要使用计时器,而不是在处理程序上调用postDelayed? - Alessandro Roaro

12
您可以从4.2开始通过编程方式将其关闭:
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(id, info);
if (info.canDisableShutterSound) {
    mCamera.enableShutterSound(false);
}

7
在点击按钮之前,请使用以下两行代码:
 AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
    mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);

这两个孤立的标签在图片之后被捕获:

AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false);

我只知道这个解决方案,且我个人在我的应用程序中使用过它。


谢谢,它可以工作,但是需要在1秒后取消静音,这样在捕获时就不会有声音。 - PankajAndroid

1
如harism所述,由于某些市场(例如日本)存在法律要求拍照时始终会产生有声快门声,因此在某些设备上无法实现这一点。
用于此类声音的流类型是STREAM_SYSTEM_ENFORCED,并且有一个只读系统属性确定是否可以静音此类流。

感谢Micheal和Harism,问题可以通过以下方法解决:静音: AudioManager mgr =(AudioManager)context.getSystemService(context.AUDIO_SERVICE); mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);取消静音: final Handler handler = new Handler(); Timer t = new Timer(); t.schedule(new TimerTask() { public void run() { handler.post(new Runnable() { public void run() { AudioManager mgr = (AudioManager)context.getSystemService(context.AUDIO_SERVICE); mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false); } }); } }, 1000); - PankajAndroid
@PankajJolapara 你可以将自己的解决方案发布为答案,并接受解决了你问题的答案。这有助于任何遇到相同问题的人。 :) - dumbfingers
有些设备无法使用所提出的解决方案,因为它们被设置为始终将快门声路由到扬声器并且不允许静音。同样,这在很大程度上取决于设备销售的市场。 - Michael

0

嗯,所有这些解决方案都很好,但我更喜欢在执行以下操作之前将音量设置为0(不仅仅是系统,因为某些设备使用其他流而不是系统和/或并非所有流都包括系统):

像这样的东西可以完美地工作:

Camera mCamera = null;

function takePicture() {
   storeSoundSettings();
   setMuteAll(true);
   // init camera and such.
   Camera.CameraInfo info = new Camera.CameraInfo();
   Camera.getCameraInfo(IdOfCameraBackOrFront, info);
       if (info.canDisableShutterSound) {
           camera.enableShutterSound(false);
       }
   setMuteAll(false);
   recoverSoundSettings();
}

并存储、恢复和设置静音等类似操作:

int[] streams = new int[]{
                AudioManager.STREAM_ALARM,
                AudioManager.STREAM_DTMF,
                AudioManager.STREAM_MUSIC,
                AudioManager.STREAM_NOTIFICATION,
                AudioManager.STREAM_RING,
                AudioManager.STREAM_SYSTEM,
                AudioManager.STREAM_VOICE_CALL};
JSONObject json;
AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

public void storeSoundSettings() {
        json = new JSONObject();
        json.put("mode", manager.getMode());
        json.put("ringermode", manager.getRingerMode());

        for (int stream : streams) {
            json.put("stream_" + stream, manager.getStreamVolume(stream));
         }
}


public void recoverSoundSettings() {
        json = new JSONObject(readString("last_audio_setting", null));
        manager.setMode(json.getInt("mode"));
        manager.setRingerMode(json.getInt("ringermode"));

        for (int stream : streams) {
            manager.setStreamVolume(stream, json.getInt("stream_" + stream), AudioManager.FLAG_ALLOW_RINGER_MODES);
}

public void setMuteAll(boolean mute) {

    for (int stream : streams) {
        manager.setStreamMute(stream, mute);
        if (mute) {
            manager.setStreamVolume(stream, 100, AudioManager.FLAG_ALLOW_RINGER_MODES);
        } else {
            manager.setStreamVolume(stream, 0, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
        }
    }
}

不要忘记捕获异常。我已经移除了它们以便更好地突出显示。


你错了,应该是setStreamVolume反过来。 - Phuong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接