在Android上如何播放手机铃声/闹钟声音

137

我一直在寻找如何在Android中播放铃声/闹钟声的方法。

我按下一个按钮,想要播放一个铃声/闹钟声。我找不到一个简单、直接的示例。是的,我已经查看了闹钟源代码……但它并不直观,而且我无法编译它。

我无法让这个工作:

Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); 
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(this, alert);
final AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
    player.setAudioStreamType(AudioManager.STREAM_ALARM);
    player.setLooping(true);
    player.prepare();
    player.start();
}

我得到了这个错误:

04-11 17:15:27.638: ERROR/MediaPlayerService(30): Couldn't open fd for
content://settings/system/ringtone

所以...如果有人知道如何播放默认的铃声/闹钟,请告诉我。

我更喜欢不上传任何文件。只需播放默认的铃声即可。

13个回答

210

您可以使用以下代码播放设置好的铃声:

Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();

3
我仍然遇到错误 - 无法打开铃声内容:content://settings/system/alarm_alert。 - Bilbo Baggins
3
简单易懂。但是,根据设备不同,这种方法可能会打断在安卓设备中正在播放的其他声音(例如音乐)。 - igordc
铃声无法路由到蓝牙耳机 :( - Anuj Jain
2
铃声无法停止。如果再次开始铃声,会播放两次。stopPrevious不起作用,顺便说一下,我是使用相同的上下文对象创建铃声播放器,而不是getapplicationcontext。 - Metehan Toksoy
@MetehanToksoy,你需要跟踪Ringtone实例,例如作为类变量。然后稍后可以执行myRingtone.stop()之类的操作。 - wildcat12
显示剩余4条评论

68
如果用户从未在他们的手机上设置过闹钟,TYPE_ALARM 可能会返回 null。您可以通过以下方式解决:
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);

if(alert == null){
    // alert is null, using backup
    alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    // I can't see this ever being null (as always have a default notification)
    // but just incase
    if(alert == null) {  
        // alert backup is null, using 2nd backup
        alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);                
    }
}

1
即使URI返回的不是有效声音,也可能不会为“null”。您应该测试“RingtoneManager.getRingtone()”的返回值是否为“null”,而不仅如此。 - Attila
2017年,无法工作,无法响铃。您最近在Android上使其工作了吗? - user285594

66

这是我做事情的方式:

Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), notification);
mp.start();

这种方法类似于markov00的方式,但使用MediaPlayer而不是Ringtone,这可以防止干扰其他可能在后台播放的声音,例如音乐。


5
我尝试了最佳答案(ringtone.play),但声音可能会被切断。我使用了这种方法,它完美地奏效了。 - wyz
1
对于在其应用程序中使用任何其他音频组件的用户来说,这是更好的解决方案。 - EntangledLoops
@YumYumYum,我刚刚测试了一下,它可以正常工作。我什么都没做,只是将上面的代码放到我的setOnClickListner中。你做了什么? - feature sky

17

您的示例基本上就是我正在使用的。然而,在模拟器上它从来没有起作用,因为模拟器默认没有任何铃声,并且content://settings/system/ringtone无法解析为可播放的内容。但在我的实际手机上它工作得很好。


16
未来的谷歌搜索者:请使用 RingtoneManager.getActualDefaultRingtoneUri() 代替 RingtoneManager.getDefaultUri()。从方法名称可以知道,它会返回实际的Uri,因此您可以自由地使用它。根据 getActualDefaultRingtoneUri() 的文档:

获取当前默认声音的 Uri。这将给出实际的声音 Uri,而不是使用此功能,大多数客户端可以使用 DEFAULT_RINGTONE_URI。

同时,getDefaultUri() 则表示:

返回特定类型默认铃声的 Uri。与返回实际铃声的 sound Uri 不同,它将返回符号化的 Uri,在播放时将解析为实际声音。


13

这个可以正常工作:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
MediaPlayer thePlayer = MediaPlayer.create(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));

try {
    thePlayer.setVolume((float) (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) / 7.0)),
                        (float) (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) / 7.0)));
} catch (Exception e) {
    e.printStackTrace();
}

thePlayer.start();

2
你为什么要将体积除以7.0?这是一个常见的工作值还是你自己挖掘出来的? - ErGo_404
我挖掘出来的东西... :D - Kamran Ahmed
你为什么要使用Float.parseFloat(Double.toString(....))?因为你想要将double转换成float吗?为什么要这样做呢? - Zordid
1
这部分是多余的:Uri.parse(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))。getDefaultUri() 已经返回一个URI,不需要再将其解析成另一个URI了。 - DritanX
1
7 是流的最大音量。 - Leo DroidCoder

13

也许有些晚了,但对于任何想要解决这个问题的人来说,现在有一个新的简单解决方案。
在Kotlin中

import android.provider.Settings
val player = MediaPlayer.create(this,Settings.System.DEFAULT_RINGTONE_URI)
player.start()

上述代码将播放默认铃声,如果您想要默认的闹钟铃声,请将

Settings.System.DEFAULT_RINGTONE_URI

更改为

Settings.System.DEFAULT_ALARM_ALERT_URI


1
你救了我的一天! - hamid Mahmoodi
一些设备需要获取Settings.System.DEFAULT_RINGTONE_URI的权限。 - Yasiru Nayanajith

9
您可以使用DDMS将MP3文件推送到/sdcard文件夹中,重新启动模拟器,然后打开Media应用程序,浏览到您的MP3文件,长按它并选择“用作电话铃声”。
错误已消失!
编辑:使用Ringdroid应用程序解决了通知声音(例如短信)的相同问题。

5
public class AlarmReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(final Context context, Intent intent) {
        //this will update the UI with message
        Reminder inst = Reminder.instance();
        inst.setAlarmText("");

        //this will sound the alarm tone
        //this will sound the alarm once, if you wish to
        //raise alarm in loop continuously then use MediaPlayer and setLooping(true)
        Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
        if (alarmUri == null) {
            alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
        }
        Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
        ringtone.play();

        //this will send a notification message
        ComponentName comp = new ComponentName(context.getPackageName(),
                AlarmService.class.getName());
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

1
AlarmService 是从哪里来的? - Eduardo Wada

3
您可以使用以下示例代码:
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone ringtoneSound = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri)

if (ringtoneSound != null) {
    ringtoneSound.play();
}

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