源码:
frameworks/base/media/java/android/media/RingtoneManager.java
frameworks/base/media/java/android/media/Ringtone.java
frameworks/base/core/java/android/preference/RingtonePreference.java
packages/providers/MediaProvider/src/com/android/providers/media/RingtonePickerActivity.java
packages/apps/Settings/src/com/android/settings/DefaultRingtonePreference.java
(代码基于高通MSM8625 4.1.2)
总体介绍:RingtoneManager 负责所有铃声的管理工作,对外提供接口供第三方 读取铃声和设置铃声;Ringtone 基本就是一个铃声对象,里面存储铃声的基本信息和一 些基本的操作;RingtonePreference 就是一个铃声的基类;RingtonePickActivity 就是我们用户见到的铃声的选择界面;DefaultRingtonePreference 基础自 RingtonePreference,同时重写了RingtonePreference中的一些重要方法。
RingtoneManager.java 分析:
重要方法: setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri);设置系统铃声
getActualDefaultRingtoneUri(Context context, int type);获取系统铃声
其中还有一些重要的方法,但是多数都是private,有兴趣的可以自己研究一下。
Ringtone.java 分析:改类封装了铃声的uri 、title、类型 等相关信息,同时在该类中实现了一个MediaPlayer,并对播放铃声和停止铃声做了相应的封装。
RingtonePreference.java 分析:该类是铃声的基类,在该类初始化的时候会从系统中读入默认的铃声类型,是否显示 默认铃声和静音(下文中会讲到);同时该类实现了onClick、onPrepareRingtonePickerIntent、onActivityResult 等方法,但是这些方法只能处理系统铃声,当通过音乐播放器设置铃声的时候就会出问题。
RingotonePickerActivity.java 分析:该类是用于铃声选择的activity,但是在高通提供的代码中确实将该activity做成了dialog的形式(android:theme="@*android:style/Theme.Holo.Dialog.Alert")
DefaultRingtonePreference.java 分析: DefaultRingtonePreference 继承自RingtonePreference,同时实现了onClick、onPrepareRingtonePickerIntent、onActivityResult,这样我们可以通过重写父类的方法来实现设置系统或者外部T卡铃声为系统铃声的功能。
onActivityResult 方法源码:(该方法便是通过重新的方式实现铃声选择的多样化)
@Override
public boolean onActivityResult(int requestCode,int resultCode, Intent data) {
switch (mSelectedItem) {
case SELECT_SYSTEM:
resetSelection();
return super.onActivityResult(requestCode, resultCode, data);
case SELECT_EXTERNAL:
resetSelection();
if (data != null) {
Uri uri = data.getData();
if (callChangeListener(uri != null ? uri.toString() : "")) {
onSaveRingtone(uri);
}
return true;
}
}
return false;
}
设置铃声的流程:
下面以在 设置-声音 中设置铃声为例 讲解整个设置铃声的过程:
1.首先 系统加载到 SoundSettings 然后判断是双卡还是
2.单卡 双卡则:com.android.settings.multisimsettings.MultiSimSettingTab
单卡则:com.android.settings.DefaultRingtonePreference
3.DefaultRintonePreference.onClick() 显示可供选择的应用(系统铃声、外部存储的铃声)
4.系统弹出对话框,用户选择应用 , 用户单击之后
mSelectedItem = which;
DefaultRingtonePreference.super.onClick();
会走上面的两行代码,这样就知道用户点击的是那个应用
5.当
点击系统铃声时 会走RingtonePickActivity
点击外部存储的铃声 会发出 android.intent.action.RINGTONE_PICKER , 一般都会被 MusicPicker.java 处理(packages/apps/Music/src/com/android/music/MusicPicker.java)
6.当用户点击确定设置铃声的时候系统会回调DefaultRingtonePreference.onActivityResult 方法,当
通过外部应用时RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri)
通过系统时 super.onActivityResult(requestCode, resultCode, data)
使用技巧:
<1> 在高通提供的铃声选择中是可以在铃声选择界面添加 默认铃声 和 静音 两个选项的
frameworks/base/core/res/res/values/styles.xml
<item name="android:showDefault">true</item>
<item name="android:showSilent">true</item>
上述 两个item 可以控制 默认铃声和静音的显示。
<2>默认铃声的配置
build/target/product/full_base.mk
PRODUCT_PROPERTY_OVERRIDES += \
ro.config.ringtone=Ring_Synth_04.ogg \
ro.config.notification_sound=pixiedust.ogg
系统开机后将这些值加载到数据库中,如果系统中配置了这些值,系统会自动找到这些值
并显示为默认值,如果没有找到,系统会将铃声选择界面中的第一个选项作为默认值。
<3>添加铃声删除铃声
系统铃声在 frameworks/base/data/sounds 目录下面
1.增加铃声:将要增加的铃声拷贝到该目录下(最好自己新建一个目录),更改mk文件(文件就在sounds根目录下),将自己要加
的铃声添加到mk文件中(如:$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Lock.ogg \)
2.删除铃声:删除铃声不是真正的让你把某个铃声文件删除,你只要在mk文件中删除掉对于的编译代码即可
3.编译问题:当要删除铃声时,建议先将system/media/audio 目录清空,否则 有可能你删除了的铃声还会被编译进去。
上述内容均为个人理解,如有错误欢迎指正