10月份什么都没写,怪不好意思的,今天赶紧补上一篇。这博客我是先在haroopad(ubantu)上写完之后才贴到优快云的markDown编辑器里的。效果非常棒,推荐
1.出厂默认铃声设置:
vendor/xiaomi(huawei and so on)/ config/common_full_phone.mk
# Default ringtone
PRODUCT_PROPERTY_OVERRIDES += \
ro.config.ringtone=Ring_Synth_04.ogg \
ro.config.notification_sound=pixiedust.ogg \
ro.config.alarm_alert=Alarm_Classic.ogg \
ro.config.mms_notification=pixiedust.ogg \
ro.config.mail_send=pixiedust.ogg \
ro.config.calendar_notification=pixiedust.ogg
2.读取mk的设置
//只有MediaScanner的构造函数中会调用,可能是刚开机的时候会ScanFile,具体
//先不深究
public MediaScanner(Context c, String volumeName) {
native_setup();
mContext = c;
mPackageName = c.getPackageName();
mVolumeName = volumeName;
mBitmapOptions.inSampleSize = 1;
mBitmapOptions.inJustDecodeBounds = true;
setDefaultRingtoneFileNames();
...
private void setDefaultRingtoneFileNames() {
mDefaultRingtoneFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
+ Settings.System.RINGTONE);
mDefaultNotificationFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
+ Settings.System.NOTIFICATION_SOUND);
mDefaultAlarmAlertFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX + Settings.System.ALARM_ALERT);
}
//DEFAULT_RINGTONE_PROPERTY_PREFIX = “ro.config”
//Settings.System.RINGTONE = ringtone
这个地方mk的值是怎么进来的,目前我还不懂。
3.设置铃声
...
//扫描到这几个文件夹的时候
private static final String RINGTONES_DIR = "/ringtones/";
private static final String NOTIFICATIONS_DIR = "/notifications/";
private static final String ALARMS_DIR = "/alarms/";
//boolean变量为true
boolean ringtones = (lowpath.indexOf(RINGTONES_DIR) > 0);
boolean notifications = (lowpath.indexOf(NOTIFICATIONS_DIR) > 0);
boolean alarms = (lowpath.indexOf(ALARMS_DIR) > 0);
...
//每次调用多个参数只有一个为true,其他为false.因为当前文件夹只有可能是其中之一
result = endFile(entry, ringtones, notifications, alarms, music, podcasts);
...
if (notifications && !mDefaultNotificationSet) {
if (!TextUtils.isEmpty(mDefaultNotificationFilename)) {
if (doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename))
needToSetSettings = true;
}
} else if (ringtones && !mDefaultRingtoneSet) {
if (!TextUtils.isEmpty(mDefaultRingtoneFilename)) {
if (doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename))
needToSetSettings = true;
}
} else if (alarms && !mDefaultAlarmSet) {
if (!TextUtils.isEmpty(mDefaultAlarmAlertFilename)) {
if (doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename))
needToSetSettings = true;
}
}
...
//如果需要设置,则调用setRingtoneIfNotSet
if(needToSetSettings) {
if (notifications) {
setRingtoneIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
mDefaultNotificationSet = true;
} else if (ringtones) {
// memorize default system ringtone persistently
setRingtoneIfNotSet(Settings.System.DEFAULT_RINGTONE, tableUri, rowId);
setRingtoneIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
if (TelephonyManager.getDefault().isMultiSimEnabled()) {
int phoneCount = TelephonyManager.getDefault().getPhoneCount();
for (int i = PhoneConstants.SUB2; i < phoneCount; i++) {
// Set the default setting to the given URI for multi SIMs
setRingtoneIfNotSet((Settings.System.RINGTONE + "_" + (i+1)), tableUri, rowId);
}
}
mDefaultRingtoneSet = true;
} else if (alarms) {
setRingtoneIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
mDefaultAlarmSet = true;
}
}
private void setRingtoneIfNotSet(String settingName, Uri uri, long rowId) {
if (wasRingtoneAlreadySet(settingName)) {
return;
}
ContentResolver cr = mContext.getContentResolver();
String existingSettingValue = Settings.System.getString(cr, settingName);
if (TextUtils.isEmpty(existingSettingValue)) {
final Uri settingUri = Settings.System.getUriFor(settingName);
final Uri ringtoneUri = ContentUris.withAppendedId(uri, rowId);
RingtoneManager.setActualDefaultRingtoneUri(mContext,
RingtoneManager.getDefaultType(settingUri), ringtoneUri);
}
Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
}
public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) { final ContentResolver resolver = context.getContentResolver();
String setting = getSettingForType(type);
if (setting == null) return;
//将设置的内容写入Setting数据库
//该数据库内容可以这么查询
//adb shell settings get system [key](查询setting数据库底下的system表的【key】对应的value)
Settings.System.putStringForUser(resolver, setting,
ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());
// Stream selected ringtone into cache so it's available for playback
// when CE storage is still locked
if (ringtoneUri != null) {
final Uri cacheUri = getCacheForType(type);
if (cacheUri != null) {
try (InputStream in = openRingtone(context, ringtoneUri);
OutputStream out = resolver.openOutputStream(cacheUri)) {
//将铃声写入data/system_de/ringtones目录下缓存
Streams.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
}
}
}
}
4.在设置中修改铃声设置
这个比较简单。用户修改之后,对Setting数据库就行写入就行。
5.来电话时
调用
RingtoneManager.getRingtone()
RingtoneManager.play();
6.小知识
(1)铃声文件的设置,播放等等一般用Uri传递,比如这样的:
content://media/external/file/84
== adb shell 进入/data/data/com.android.providers.media/databases ==
这个路径底下有个external.db
uri所对应的内容在这个db里就能查到。查询方法:
sqlite3 external.db//进入对应db.
select * from files where _id=84;
7.自定义铃声
- 将.ogg文件放到
android/frameworks/base/data/sounds/
目录 - 修改android/build/target/product/core_base.mk
PRODUCT_PROPERTY_OVERRIDES := \
ro.config.notification_sound=OnTheHunt.ogg \
ro.config.alarm_alert=Alarm_Classic.ogg
//ro.config.alarm_alert=<需要修改的.ogg>
- 修改/frameworks/base/data/sounds/AllAudio.mk:
PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
$(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \