setMicrophoneMute(boolean)不适用于某些设备

时间:2011-03-07 08:29:59

标签: android

我在这里找不到任何相关的帖子(但是互联网上的其他小帖子),所以这里是:

AudioManager.setMicrophoneMute(boolean)在我测试过的某些特定设备上没有做任何事情:Google Nexus S,三星Galaxy S和摩托罗拉Milestone。 在任何其他设备上它运作良好。

它甚至保持其“状态”并返回一个布尔值,好像它被静音\取消静音,但它没有静音 - 麦克风继续记录 - 无论是在GSM通话还是在AudioRecord编程录音中。 没有指示性日志消息。

我也搞砸了权限(android.permission.MODIFY_AUDIO_SETTINGS,android.permission.RECORD_AUDIO),这里没什么新东西。

有没有人遇到过这个?有没有人有解决方法或神奇的解决方案? 如果我使用AudioRecord,我只是为这些设备实现自己的“静音” - 我不会传递录制的缓冲区。但它无法帮助我在GSM呼叫中静音麦克风,我需要它。

由于

----------------更新----------------

见下文。

4 个答案:

答案 0 :(得分:5)

嗨,我有同样的问题,我想模拟来电屏幕。 并且在该屏幕内有一个执行静音的按钮,AudioManager.setMicrophoneMute(boolean)可以在大多数手机上使用,但不能在所有手机上使用。我找到了解决它的方法。我模拟免提套件上的按静音按钮。它对我有用,希望它也能帮到你 这是代码:

Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT,new KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEYCODE_HEADSETHOOK));
getBaseContext().sendOrderedBroadcast(buttonUp,"android.permission.CALL_PRIVILEGED");

答案 1 :(得分:5)

我遇到了这个问题,因为我想编辑包含AAC音频数据的M4A文件。我希望能够合并它们并添加静音作为填充。由于不同设备每帧的毫秒数差异,我决定将麦克风静音并录制一秒静音,然后在我需要填充静音时反复重复。 (M4A + AAC静音比原始PCM复杂得多)。

不幸的是,我在Android设备上遇到了许多静音差异。这是我学到的:

  • 除非您使用MODIFY_AUDIO_SETTINGS权限,否则静音将无声地失败。没有错误消息,它只是不会静音
  • 三星Galaxy Tab 10.1和摩托罗拉Xoom正如您所料。调用audioManager.setMicrophoneMute(true)静音,并调用audioManager.setMicrophoneMute(false)取消静音
  • HTC Inspire(使用CyanogenMod 7)和Motorola Droid X将错误地返回true到audioManager.isMicrophoneMute,但实际上不会被静音。要解决此问题,请在静音之前调用audioManager.setMode(AudioManager.MODE_IN_CALL)。一旦完成静音,请务必将模式更改回原来的状态 - 我不确定,但如果您将其设置为错误的模式,其他应用程序可能会出现问题。
  • HP Touchpad被黑客攻击到CyanogenMod 7的双重启动,根本不喜欢静音。它产生无用的录制文件,并且对audioManager.setMode()的调用需要五秒钟才能返回。
  • HTC MyTouch 4G声称它已静音,但在我能找到的任何条件下都不会静音。
  • HTC Flyer将静音,但只要您调用mediaRecorder.start()或mediaRecorder.stop(),它就会取消静音。你可以再次静音,但可能会先听到一小部分声音。
  • 姜饼设备,无论您是否想要它们,在任何MediaRecorder录制开始时都会有半秒到一秒的静音。整体录音的长度是正确的,第一部分只是静音而不是捕捉麦克风当时接收的内容。

在我的情况下,为了生成一个静音文件,给定设备使用每帧的适当毫秒数(因此在与其他音频文件合并时它是兼容的),我使用类似的代码:

AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int oldAudioMode = audioManager.getMode();
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setMicrophoneMute(true);
MediaRecorder mediaRecorder = new MediaRecorder();
int bitRate = 1000 * 160;
mediaRecorder.setAudioEncodingBitRate(bitRate);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(silenceFile.getAbsolutePath());
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioSamplingRate(44100);
try {
    mediaRecorder.prepare();
} catch (IOException ioe) {
    throw new RuntimeException("could not prepare mediarecorder to create silence file",ioe);
}
mediaRecorder.start();
audioManager.setMicrophoneMute(true); //re-mute for devices like HTC Flyer that unmute
try {
    Thread.sleep(SILENCE_LENGTH_MILLIS);
} catch (InterruptedException ie) {
    throw new RuntimeException("could not record silence file", ie);
}
mediaRecorder.stop();
audioManager.setMicrophoneMute(false);
audioManager.setMode(oldAudioMode);
int currentVersion = android.os.Build.VERSION.SDK_INT;
if (currentVersion <= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
    //cut out beginning half second and use that, since it's always silent on Gingerbread
} else {
    //Honeycomb and up
    //Take end of audio and use that--if the device unmuted itself there may be a little noise at the beginning
}

这是一个完整的解决方案吗?不会。有些设备不会静音。如果您尝试静音,其他设备(如前面提到的HP Touchpad)会导致所有新问题。希望这些技巧至少可以帮助人们在大多数Android设备上静音。

答案 2 :(得分:3)

未找到解决方案。如果录制的音频用作数据缓冲区,请使用静音PCM数据(填充零)。如果您需要以编程方式静音常规电话,请通知用户此设备需要通过呼叫屏幕进行手动静音。

我认为这是最终答案,但请让我感到惊讶。

答案 3 :(得分:0)

你可以试试这个:

AudioManager audioManager = ((AudioManager)context.getSystemService(Context.AUDIO_SERVICE));
    audioManager.setMode(AudioManager.MODE_NORMAL);
    if(state) //state-boolean 
    {
        audioManager.setMicrophoneMute(false);
        audioManager.setMode(AudioManager.MODE_IN_CALL);
        state= false;
    }
    else
    {
        audioManager.setMicrophoneMute(true);
        state = true;
    }