如何播放安卓通知音?

190

我想知道如何在不通过媒体流播放声音的情况下播放通知声音。目前我可以通过媒体播放器实现这一点,但我不希望它以媒体文件的形式播放,而是希望它作为通知、警报或铃声来播放。以下是我当前代码的示例:

MediaPlayer mp = new MediaPlayer();
mp.reset();
mp.setDataSource(notificationsPath+ (String) apptSounds.getSelectedItem());
mp.prepare();
mp.start();
11个回答

472

如果还有人在寻找解决方案,我在How to play ringtone/alarm sound in Android找到了答案。

try {
    Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
    r.play();
} catch (Exception e) {
    e.printStackTrace();
}

你可以将TYPE_NOTIFICATION更改为TYPE_ALARM,但你需要跟踪你的铃声(Ringtone r),以便在用户点击按钮或其他情况下停止播放它。


2
例如,摩托罗拉手机扩展了首选项活动,并允许用户为短信和其他类别定义通知声音。上述方法在这种类型的手机上不起作用。您有任何解决此问题的想法吗? - David
2
我在这里遇到了一个错误:MediaPlayer - 应该已经设置了字幕控制器。这是什么意思? - Deqing
1
为什么你要捕获每一个异常?哪一个可能会被抛出? - Miha_x64
1
我遇到了“无法打开content://settings/system/notification_sound_cache: java.io.FileNotFoundException”错误。我已经通过使用“Uri notification = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION);”解决了这个问题。在这里,我使用了“getActualDefaultRingtoneUri”而不是“getDefaultUri”。 - Dhaval Patel
2
@Sam,是的。https://stackoverflow.com/q/39876885/2614353。基本上,不要每次播放时都创建一个RingTone对象。只需创建一次,然后多次播放同一对象即可。 - Tom Bevelander
显示剩余2条评论

208

现在您可以在构建通知时包含声音,而无需单独调用声音。

//Define Notification Manager
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

//Define sound URI
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext())
        .setSmallIcon(icon)
        .setContentTitle(title)
        .setContentText(message)
        .setSound(soundUri); //This sets the sound to play

//Display notification
notificationManager.notify(0, mBuilder.build());

13
这解决的是一个不同的问题,不是“如何播放通知声音”,而是“如何播放通知并同时显示声音”。被接受的答案在其解决方案中是合理的。 - Fabian Tamp
7
或许你也应该将其设置为通过STREAM_NOTIFICATION播放,这样它就会随着操作系统当前的通知音量偏好进行播放:.setSound(soundUri, AudioManager.STREAM_NOTIFICATION)。 - mwk
@Rob Riddle,它能正常工作。但是在多个通知(例如100个通知并行)的情况下,声音会与下一个通知的声音混合在一起。从逻辑上讲,如果声音正在播放,它应该等待前一个播放完成。您能否在这种情况下提供帮助? - Waqas Ali Razzaq
当应用程序在后台运行时不播放声音。有什么建议吗? - Sagar Nayak

50
如果您想播放默认通知提示音,那么可以使用NotificationCompat.Builder类的setDefaults(int)方法:
NotificationCompat.Builder mBuilder =
        new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(someText)
                .setDefaults(Notification.DEFAULT_SOUND)
                .setAutoCancel(true);

我相信这是完成您任务最简单的方式。


当应用程序在后台运行时不播放声音。有什么建议吗? - Sagar Nayak

20

试一下这个:

public void ringtone(){
    try {
        Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
        r.play();
     } catch (Exception e) {
         e.printStackTrace();
     }
}

9

虽然你的问题已经有一段时间了,但是...您是否尝试设置音频流类型?

mp.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);

在准备之前必须完成。


2
我有一个差不多的问题。经过一些研究,我认为如果你想播放默认系统“通知声音”,你基本上必须显示一个通知并告诉它使用默认声音。在其他答案中有一些争议,如果你正在播放通知声音,你应该同时呈现一些通知消息。
然而,稍微调整一下通知API,你就可以接近你想要的效果。你可以显示一个空白通知,然后在几秒钟后自动删除它。我认为这对我有用;也许对你有用。
我已经在 com.globalmentor.android.app.Notifications.java 中创建了一组方便的方法,允许你创建一个通知声音,如下所示:
Notifications.notify(this);

LED 灯会闪烁,如果您开启了震动权限,也会有震动提示。通知图标会出现在状态栏中,但几秒后会消失。
此时您可能会意识到,既然通知无论如何都会消失,那么在通知栏上显示一个滚动消息也没有关系,可以按以下方式实现:
Notifications.notify(this, 5000, "This text will go away after five seconds.");

这个类中还有许多其他方便的方法。您可以从其Subversion存储库下载整个库,并使用Maven构建它。它依赖于globalmentor-core库,该库也可以使用Maven构建和安装。


这太复杂了,只是为了播放一个声音。你可以用这种方法:https://dev59.com/xm855IYBdhLWcg3wQyDh#9622040 - slinden77

2
Intent intent = new Intent(this, MembersLocation.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.putExtra("type",type);
    intent.putExtra("sender",sender);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    String channelId = getString(R.string.default_notification_channel_id);

    Uri Emergency_sound_uri=Uri.parse("android.resource://"+getPackageName()+"/raw/emergency_sound");
   // Uri Default_Sound_uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    if(type.equals("emergency"))
    {
        playSound=Emergency_sound_uri;
    }
    else
    {
        playSound= Settings.System.DEFAULT_NOTIFICATION_URI;
    }

    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(this, channelId)
                    .setSmallIcon(R.drawable.ic_notification)
                    .setContentTitle(title)
                    .setContentText(body)
                    .setSound(playSound, AudioManager.STREAM_NOTIFICATION)
                    .setAutoCancel(true)
                    .setColor(getColor(R.color.dark_red))
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setContentIntent(pendingIntent);

   // notificationBuilder.setOngoing(true);//for Android notification swipe delete disabling...

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    // Since android Oreo notification channel is needed.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(channelId,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_HIGH);
        AudioAttributes att = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                .build();
        channel.setSound(Emergency_sound_uri, att);
        if (notificationManager != null) {
            notificationManager.createNotificationChannel(channel);
        }
    }

    if (notificationManager != null) {
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
}

1
感谢您提供这段代码片段,它可能会提供一些有限的、即时的帮助。一个适当的解释将极大地提高其长期价值,因为它可以展示为什么这是一个好的问题解决方案,并使其对未来读者有其他类似问题的人更有用。请[编辑]您的答案以添加一些解释,包括您所做的假设。 - NOhs

1

我认为“通知声音”的概念在Android UI中有些错误。

Android的预期行为是使用标准通知来提醒用户。如果您播放通知声音而没有状态栏图标,那么会让用户感到困惑(“那是什么声音?这里没有图标,也许我听力有问题?”)。

如何设置通知声音,例如在这里:设置通知声音


1
不一定,这可能是应用内通知。例如,如果你在聊天应用程序中有小的音效,用于传入和传出消息,则本质上是通知,当手机在静音模式时,你希望它们停止发出声音。 - copolii
好的,你说得没错,但那是另外一回事。我在谈论(假设这是问题的主题)“系统通知声音”,也就是在Android系统GUI上的声音。当然,当你进入自己的应用程序时,一切都由你决定。 - think01

0

7
我不想显示通知,只想播放声音。 - ninjasense

0

设置声音到通知通道

        Uri alarmUri = Uri.fromFile(new File(<path>));

        AudioAttributes attributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_ALARM)
                .build();

        channel.setSound(alarmUri, attributes);

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