LoginSignup
5
3

More than 1 year has passed since last update.

Androidでミュートの解除/設定をする

Posted at

はじめに

この記事はAndroid Advent Calendar 2022 24日目の記事です。

やりたかったことはAndroidで強制的に音を鳴らすことだったのですが、ミュート解除周りでハマったのでその時の話を書きます。

コードからミュートを解除する

adjustStreamVolumeを使う

コードからミュートを解除するにはAudioManagerのメソッドであるadjustStreamVolumeを使うとできます。このメソッドは音量を調節するためのメソッドですが、ミュートとアンミュートを指定することができます。
第一引数には使用したいストリームを指定します。今回はアラーム音のためのストリームであるSTREAM_ALARMを使用します。第2引数には音量を上げるか下げるかを指定することができます。この第2引数にADJUST_UNMUTEを指定すると、ミュートを解除することができます。
第3引数は flag です。今回は0で大丈夫です。

この辺りの定数に関してはこちらをご覧ください。

val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager

try {
    audioManager.adjustStreamVolume(
        AudioManager.STREAM_ALARM,
        AudioManager.ADJUST_UNMUTE,
        0
    )
    // 音量を5に設定
    audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 5, 0)
} catch (e: Exception) {
Timber.e("ミュートの解除に失敗しました。", e)
}

しかし、実はこれだと端末によっては通知オフ状態(サイレントモード)は解除できません。バイブレーションモードのみ解除することができます。

ringerModeを変更する

別の方法として、ringerModeを変更する方法があります。
AudioManagerringerModeRINGER_MODE_NORMALに変更します。

val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager

try {
    audioManager.ringerMode = AudioManager.RINGER_MODE_NORMAL

    // 音量を5に設定
    audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 5, 0)
} catch (e: Exception) {
Timber.e("ミュートの解除に失敗しました。", e)
}

コードからサイレントモードを設定する

ミュートを解除して必要な効果音等を鳴らした後、もう一度サイレントモードやバイブレーションモードに戻したいですよね。

サイレントモードやバイブレーションモードに戻すにはまずAndroidManifestにACCESS_NOTIFICATION_POLICYのパーミッションを追加します。

<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />

その上でringerModeを元に戻します。そのために解除する時に元の状態を記憶しておく必要があります。

val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager

try {
    // 元の状態を記憶
    isVibration = audioManager.ringerMode == AudioManager.RINGER_MODE_VIBRATE
    isSilent = audioManager.ringerMode == AudioManager.RINGER_MODE_SILENT
    // サイレントモードを解除
    audioManager.ringerMode = AudioManager.RINGER_MODE_NORMAL

    // 音量を5に設定
    audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 5, 0)
} catch (e: Exception) {
Timber.e("ミュートの解除に失敗しました。", e)
}

// 元の状態に戻す
if (audioManager.ringerMode == AudioManager.RINGER_MODE_NORMAL) {
    // バイブレーションに戻す
    if (isVibration) {
        audioManager.ringerMode = AudioManager.RINGER_MODE_VIBRATE
    } else if (isSilent) {
    // サイレントモードに戻す
    audioManager.ringerMode = AudioManager.RINGER_MODE_SILENT
    }
}

しかし、ここで問題があります。

もう一度サイレントモードを解除…できない?

コードからサイレントモードに設定した後、もう一度サイレントモードを解除することができなくなります。
これはAndroidのサイレントモードの仕様が原因です。

Androidのサイレントモードの仕様

Androidには、音量から変更できるいわゆる通知オフの状態と、設定画面などから設定することができる強いサイレントモードの2種類があります。
コードからサイレントモードの設定をすると、この強いサイレントモードに移行してしまいます。
そして、この強いサイレントモードは、端末によってあったりなかったりします。設定の方法もバラバラです。
社内のいくつかの検証端末で確認した結果、以下のような結果になりました。

機種名 OSバージョン 強いサイレントモードの有無 設定場所
Pixcel 6 Pro 11 あり コントロールセンター
Xperia 10 Ⅱ / Ⅲ 11 あり 設定画面
OPPO A55s 5G 11 あり 設定画面
Galaxy Z Flip3 5G 12 なし
HUAWEI nova lite 3 9 なし 
AQUOS R2 compact 9 なし

そして、強いサイレントモードに移行してしまうとコードからは解除できなくなってしまいます。

私が確認した中で強いサイレントモードにしか移行できない端末は以下の2つでした。この端末は通知オフを解除/設定することもできませんでした。

  • Pixcel 6 Pro
  • Xperia 10 Ⅱ / Ⅲ

通知オフの状態を解除/設定できる端末は以下の端末でした。

  • OPPO A55s 5G
  • Galaxy Z Flip3 5G

この2つに関しては、adjustStreamVolumeを使う方法で通知オフ状態の解除ができました。しかしGalaxyに関しては、通知オフ/バイブレーション状態でもringerModeがNORMALから変更されませんでした。その状態でrigerModeを変更しようとすると、アプリがクラッシュしてしまいました。

以下の端末は通知オフの状態の解除/設定はできませんでした。

  • HUAWEI nova lite 3
  • AQUOS R2 compact

まとめ

コードをからミュートを解除する方法はadjustStreamVolumeを使う方法とringerModeを変更する方法があります。しかし、サイレントモードには機種によって強いサイレントモードに移行してしまうものがあり、元の状態に戻せなくなってしまうことがありました。
結局私はadjustStreamVolumeを使うを採用し、音が鳴らない機種があることに関しては認めて貰うことになりました。。アプリ側から強いサイレントモードを設定してしまうのも、ミュート状態を元に戻さないのも理想的ではないので…
この辺り知見ある方がいらっしゃいましたら教えてくださるとありがたいです。

参考

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3