现在咱们来聊聊android系统中铃声的播放,从framework层面说说Ringtone的播放原理,我在android源码中碰到了播放系统铃声中的问题,所以仔细研究了这方面的知识,现在整理一下,给读者一些帮助,现在我对铃声的播放和设置特别亲切,不管是短信铃声方面的,来电铃声,还是日历铃声,email的铃声,闹钟的铃声,都能解决铃声方面的bug。前面我说了Notification的播放机制,Android中Notification的framework层讲解【安卓源码解析四】 . 大概给大家说了说,有想了解的可以参考看一看。铃声播放的机制都是用MediaPlayer来播放的,通过MediaPlayer来申请AudioManager机制来播放音乐铃声的。前面我写了个调用系统铃声和sdcard卡中铃声的demo,Android中铃声总结【安卓源码解析一】.这个例子中有一段代码:通过intent的action来启动一个选择系统铃声的dialog,这个到底是启动的哪儿的dialog,今天给大家揭秘一下,希望给大家带来点帮助:大明原创,转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/7166134
写一个intent来启动播放ringtone的activity:
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
// Allow user to pick 'Default'
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
// Show only ringtones
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
//set the default Notification value
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
// Don't show 'Silent'
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
startActivityForResult(intent, SMS_RINGTONE_PICKED);
这个activity启动后就跑到了framework的com.android.internal.app.RingtonePickerActivity里面去了,在framework部分也可以写activity类得,这个挺有意思的,哈哈,新发现,有种“山穷水复疑无路,柳暗花明又一村”的感觉!哈哈,这个intent的action发到哪儿去了呢??
在frameworks\base\core\res\AndroidManifest.xml中可以搜到这个action:
<activity android:name="com.android.internal.app.RingtonePickerActivity"
android:theme="@style/Theme.Dialog.Alert"
android:excludeFromRecents="true"
android:multiprocess="true">
<intent-filter>
<action android:name="android.intent.action.RINGTONE_PICKER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<action android:name="android.intent.action.RINGTONE_PICKER" />这个就是接受这个intent的action动作的对应的activity的类,找这个RingtonePickerActivity.java类,这个类的继承和实现有点特殊,注意观察:
public final class RingtonePickerActivity extends AlertActivity implements
AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
AlertController.AlertParams.OnPrepareListViewListener
这个类继承AlertActivity并实现了这么多接口,找到点击每个选项播放的方法监听:
private DialogInterface.OnClickListener mRingtoneClickListener =
new DialogInterface.OnClickListener() {
/*
* On item clicked
*/
public void onClick(DialogInterface dialog, int which) {
// Save the position of most recently clicked item
mClickedPos = which;
// Play clip
playRingtone(which, 0);
}
};
然后找到playRingtone(which, 0);这个方法去:
private void playRingtone(int position, int delayMs) {
mHandler.removeCallbacks(this);
mSampleRingtonePos = position;
mHandler.postDelayed(this, delayMs);
}
这个postDelayed(this, delayMs);this代表当前对象,因为这个类是实现了Runnable接口,所以这时候会走到run方法中去:
public void run() {
if (mSampleRingtonePos == mSilentPos) {
mRingtoneManager.stopPreviousRingtone();
return;
}
/*
* Stop the default ringtone, if it's playing (other ringtones will be
* stopped by the RingtoneManager when we get another Ringtone from it.
* by bw on start
* when it`s not null set the default ringtone is null
* modify by wangxianming in 2011-12-28
*/
if (mDefaultRingtone != null) {
/// if(mDefaultRingtone.isPlaying()){
mDefaultRingtone.stop();
/// }
mDefaultRingtone = null;
}
Ringtone ringtone;
if (mSampleRingtonePos == mDefaultRingtonePos) {
if (mDefaultRingtone == null) {
mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);
}
ringtone = mDefaultRingtone;
/*
* Normally the non-static RingtoneManager.getRingtone stops the
* previous ringtone, but we're getting the default ringtone outside
* of the RingtoneManager instance, so let's stop the previous
* ringtone manually.
*/
mRingtoneManager.stopPreviousRingtone();
} else {
ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
}
if (ringtone != null) {
ringtone.play();
}
}
这时候找到这里就基本上找到根源了,ringtone.play();就是播放ringtone音乐的方法;注意:15行,16行,我对源码进行了修改,这个有点问题,源码对原生态的音乐格式支持的很好,但是对mid格式的音乐支持的不太好,所以如果播放mid格式的音乐不能用多个mediaplayer来播放,只能用一个来播放,只能hold住一个,不能重复hold这个ringtone,所以把这个mDefaultRingtone = null;每次都置为空,这样每次都是一个对象就可以了。这样播放系统铃声就没有问题了!
再去frameworks\base\media\java\android\media\Ringtone.java这个类去找到play()方法:
public void play() {
if (mAudio == null) {
try {
openMediaPlayer();
} catch (Exception ex) {
Log.e(TAG, "play() caught ", ex);
mAudio = null;
}
}
if (mAudio != null) {
// do not ringtones if stream volume is 0
// (typically because ringer mode is silent).
if (mAudioManager.getStreamVolume(mStreamType) != 0) {
if (mIsLoop){
mAudio.setLooping(true);
}
mAudio.start();
}
}
}
找到openMediaPlayer()方法:
private void openMediaPlayer() throws IOException {
mAudio = new MediaPlayer();
if (mUri != null) {
mAudio.setDataSource(mContext, mUri);
} else if (mFileDescriptor != null) {
mAudio.setDataSource(mFileDescriptor);
} else if (mAssetFileDescriptor != null) {
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (mAssetFileDescriptor.getDeclaredLength() < 0) {
mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor());
} else {
mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(),
mAssetFileDescriptor.getStartOffset(),
mAssetFileDescriptor.getDeclaredLength());
}
} else {
throw new IOException("No data source set.");
}
mAudio.setAudioStreamType(mStreamType);
mAudio.prepare();
}
这样就把所有的ringtone播放的机制大致能搞清楚了!希望这个流程给大家一些启发!有问题的可以留言,我看到会给出解释的,希望高手指点不足之处!大明原创。
分享到:
相关推荐
最近研究源码程序,改了改手机短信铃声的源码,最近总结了下铃声的代码,写个activity继承PreferenceActivity有:手机短信铃声,手机铃声,闹钟铃声,还有sdcard中的铃声,通过选择相应的铃声,然后读取到xml文件...
MP3 To Ringtone GoldMP3转MIFF格式的软件非常好用这是破解版来的
android开关机动画开关机铃声修改方法
使用SoundPool播放音频,模拟手机选择铃声。
苹果铃声转换器加剪辑Aimersoft iPhone Ringtone Maker注册邮箱:499712083@QQ.COM 注册码: F7BBDC0EC405B819BB959515852A950F
非常方便的一款制作铃声的软件,直接同步到iphone4,不需要itunes,个性化铃声随意制作,压缩包中有注册机,最新版本,1.9.1.443版
x-iphone-ringtone-maker苹果铃声软件
iPhone Ringtone Maker是一款很好用的苹果格式铃声转换工具,是果粉们必备的一款制作.m4r铃声的好软件。它的使用非常简单,首先在输入文件右侧点击浏览,选择要转换的媒体文件,可以是视频也可以是音频文件,然后...
想制作好听的手机铃声吗?...快来试试Cool iPhone Ringtone Maker吧。本软件可以见音乐文件制作成独特的iPhone铃声,内置的音频编辑器让你可以自由剪切、拷贝、粘贴和删除文件。并且有多种特效可供选择。
手机铃声超强转换工具
- 制作无限的铃声,任意长度。 高达40秒! - 用同一个程序制作6秒或以下的通知声!(短信声/聊天工具声/等) - 无广告。 - 相容普遍的音频格式(MP3,M4A) - 微调控制按键(+/-) - 我们网站建议的铃声接入点 ...
App Android to manage diary tasks and work tasks, allowed to be notified with an alarm or/and status bar. Add, edit and delete events Events can be Task or Work types Allow notify of three ways: ...
今天就下拉菜单中添加SeekBar控制音量为例(Android 5.1系统) 一:自定义Seekbar 先来看一下所自定义的效果图: 首先来来看一下布局文件: <LinearLayout xmlns:android=...
Free Ringtone Maker是一款专业好用的Windows铃声制作软件。软件抛掉复杂的音频格式,抛掉复杂的音频截取,只需要截取所需部分,通过简单明了的几个步骤,用户就可以轻松打造属于您自己风格的铃音。软件界面美观简洁...
铃声制作工具 Free Ringtone Maker使用教程.docx
铃声随机化器Android铃声随机生成器应用。 铃声随机化程序是Google Android更改您当前铃声的简单应用程序。 您可以在每次通话后自动更改铃声,也可以使用小部件,通知或菜单本身手动更改它。 ================== ...
mp3剪裁大师「MP3 Cutter & Ringtone Maker」 v1.0.86.02 for Android 准确切出音乐歌曲或音频文件的最爱部分
android的消息提示(震动和提示音),实现代码如下所示: public class VibratorUtil { protected AudioManager audioManager; protected Vibrator vibrator; private Ringtone ringtone; private static ...
Free Ringtone Maker是一个轻松创建你自己的铃声软件。3个简单步骤就可以制作铃声。只需选择一首歌曲,削减拖动一个滑块。您还可以添加一些淡入和淡出的铃声效果。
因为有个需求是在自己的app中添加铃声并播放,而之前在网上查阅了相关的资料却大多都是教人怎么设置手机来电、闹钟等手机系统的功能,所以就以此文章作为记录。 一、本篇文章的大致内容是 1.调用系统铃声界面选择...