开发者

setMicrophoneMute(boolean) doesn't work on some devices

I couldn't find any related post here (but other small posts on the internet), so here it is:

AudioManager.setMicrophoneMute(boolean) doesn't do anything on some particular devices that I tested with: Google Nexus S, Samsung Galaxy S and Motorola Milestone. On any other device it works well.

It even maintains its "state" and returns a boolean as if it got muted\unmuted, but it doesn't mute - microphone continues to record - both in GSM call and in AudioRecord programmatic recording. There is no indicative log message.

I also messed with permissions (android.permission.MODIFY_AUDIO_SETTINGS, android.permission.RECORD_AUDIO), nothing new here.

Did anyone else encounter that? Does anyone have a workaround or a magic solution? If I use AudioRecord I just implement my own "mute" for these devices - I don't pass on the recorded buffers. But it can't help me with muting the mic in a GSM call, which I need.

Thanks

开发者_JAVA技巧

---------------- Update ----------------

See below.


I had this problem because I wanted to edit M4A files containing AAC audio data. I wanted to be able to merge them and add silence as padding. Due to the difference in the number of milliseconds per frame across different devices, I decided to mute the microphone and record a second of silence, then repeat that over and over whenever I needed to pad silence. (M4A + AAC silence is MUCH more complicated than raw PCM).

Unfortunately, I ran into many muting differences across Android devices. Here is what I learned:

  • Muting will silently fail unless you use the MODIFY_AUDIO_SETTINGS permission. No error message, it just won't mute
  • The Samsung Galaxy Tab 10.1 and Motorola Xoom work as you would expect. Call audioManager.setMicrophoneMute(true) to mute and audioManager.setMicrophoneMute(false) to unmute
  • The HTC Inspire (with CyanogenMod 7) and Motorola Droid X will incorrectly return true to audioManager.isMicrophoneMute, but will not actually be muted. To fix this, before you mute, call audioManager.setMode(AudioManager.MODE_IN_CALL). Make VERY sure to change the mode back to what it was originally once you are done muting--I'm not certain, but it looked like there may be issues in other apps if you leave it set on the incorrect mode.
  • The HP Touchpad, hacked to dualboot to CyanogenMod 7, does not like muting at all. It produces useless recording files, and calls to audioManager.setMode() take five seconds to return.
  • The HTC MyTouch 4G claims it is muted, but will not mute itself under any conditions that I can find.
  • The HTC Flyer will mute, but as soon as you call mediaRecorder.start() or mediaRecorder.stop() it will unmute itself. You can mute it again, but may catch a fraction of a second of sound first.
  • Gingerbread devices, whether you want them to or not, will have between half a second and a second of silence at the beginning of any MediaRecorder recording. The overall recording is the correct length, this first part is just silenced instead of capturing what the microphone was receiving at the time.

In my case, to generate a silence file with the appropriate number of millis per frames the given device uses (so it is compatible when merging with other audio files), I use code similar to this:

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
}

Is this a complete solution? No. Some devices just will NOT mute. Other devices, like the previously mentioned HP Touchpad, cause all new problems if you even attempt to mute. Hopefully these tips will at least help people mute on a majority of Android devices.


Hi i had the same problem i wanted to simulate incoming call screen. and within that screen a button that perform mute, and the AudioManager.setMicrophoneMute(boolean) worked on most phones but not on all of them. i found a way to get around it. i simulate a press on mute button on the handsfree kit . it worked for me hope it will help you too here is the code:

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");


No solution was found. If the recorded audio is used as a data buffer, use silence PCM data (fill with zeros). If you need to mute a regular phone call programmatically, inform the user that this device requires manual muting from the call screen.

I consider this as the final answer, but please surprise me.


you can try with this:

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;
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜