Android Foreground Service 中,提示音循环播放及停止

发布时间: 2023-08-05 11:13:06 作者: 大象笔记

需求背景

Android App 收到蓝牙推送的消息之后,播放提示音,且一直播放,直到收到停止的指令。

TODO

下载报警提示音

https://pixabay.com/sound-effects/search/alert/

在 Android Studio 项目的 res 目录下,新建一个 raw 目录,将下载到的 mp3 音频文件放进去。

例如,命名为 alert.mp3

播放报警提示音

由于是在 Foreground Service 中播放音频,所以为了方便 fragment 中调用,使用了静态变量和方法。

同时 Foreground Service 的静态方法中无法获取 context,所以加上了 Context 参数。

private static MediaPlayer mediaPlayer;

public static void playAlertAudio(Context context) {
	if (mediaPlayer != null && mediaPlayer.isPlaying()) {
		// 防止重复播放
		return;
	}

	mediaPlayer = MediaPlayer.create(context, R.raw.alert);
	mediaPlayer.setLooping(true);
	mediaPlayer.start();
}

停止播放

public static void stopAlertAudio() {
	if (mediaPlayer != null && mediaPlayer.isPlaying()) {
		mediaPlayer.stop();
		mediaPlayer.reset();
	}
}

Foreground Servie 中调用

BLE 监听回调中:

NodeConnectionService.playAlertAudio(getApplicationContext());

Fragment 中调用

按钮点击事件中:

NodeConnectionService.playAlertAudio(getContext());

华为鸿蒙系统上的诡异问题

这个功能在台电的 Android 平板上及小米手机上运行的很正常,但是在华为鸿蒙的平板上,有明显的问题。

就是如果信号源短时间内发送了多个报警,这个音频停不下来,或是同时播放了多个音频。即过滤没有成功。

增加了两项针对性的改进:

修改后的代码:

    private static MediaPlayer mediaPlayer;
    private static boolean isPlayingAlert = false;

    public static void playAlertAudio(Context context) {
        if (mediaPlayer != null && isPlayingAlert) {
            // 防止重复播放
            return;
        }

        isPlayingAlert = true;

        mediaPlayer = MediaPlayer.create(context, R.raw.alert);

        mediaPlayer.setLooping(true);
        mediaPlayer.start();

    }

    public static void stopAlertAudio() {
        if (mediaPlayer != null && isPlayingAlert) {
            mediaPlayer.stop();
            mediaPlayer.reset();
            isPlayingAlert = false;
        }
    }
我是一名山东烟台的开发者,联系作者