前景提示:
关于系统铃声闹铃的设置使用的是frameworks/base/media/java/android/media/RingtoneManager.java
设置铃声:RingtoneManager.setActualDefaultRingtoneUri()方法
public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
String setting = getSettingForType(type);
if (setting == null) return;
final ContentResolver resolver = context.getContentResolver();
if (Settings.Secure.getIntForUser(resolver, Settings.Secure.SYNC_PARENT_SOUNDS, 0,
context.getUserId()) == 1) {
// Parent sound override is enabled. Disable it using the audio service.
disableSyncFromParent(context);
}
if(!isInternalRingtoneUri(ringtoneUri)) {
ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
}
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) {
//*******这里有个新增声音种类bug,添加一个过滤if直接return*****
//这块代码大概是要做一个声音的存储调取缓存的操作,若是我们新增声音进行存储调取的话,会出现io错误,还是直接屏蔽了,有大手子其他理解可交流下
//过滤返回代码 if(setting .equals(Settings.System.MODEL_TIMER) ))return;
final Uri cacheUri = getCacheForType(type, context.getUserId());
try (InputStream in = openRingtone(context, ringtoneUri);
OutputStream out = resolver.openOutputStream(cacheUri)) {
FileUtils.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
}
}
}
获取铃声:
RingtoneManager.getActualDefaultRingtoneUri();
关于默认铃声设置修改的方法
第一种:网上搜索到的几乎都是这种默认修改参数文件路径的方式
build/make/target/product/full_base.mk 或者是其他能编译到的.mk文件
PRODUCT_PROPERTY_OVERRIDES := \
ro.config.ringtone=Ring_Synth_04.ogg \(这个对应的是铃声默认文件,Ring_Synth_04.ogg不过当你解析出来后title是 Flutey Phone,这是因为在数据库中被修改了title值)
ro.config.notification_sound=pixiedust.ogg
/data/sounds下.mk文件中有很多铃声资源文件供查找替换.mk的Ring_Synth_04.ogg使用/frameworks/base/data/sounds/AudioPackageGo.mk
关于系统默认资源文件修改操作:
添加资源路径/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<string name="def_desk_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
<string name="def_desk_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
<string name="def_car_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
<string name="def_car_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
<integer name="def_lockscreen_sounds_enabled">1</integer>
<string name="def_lock_sound" translatable="false">/product/media/audio/ui/Lock.ogg</string>
<string name="def_unlock_sound" translatable="false">/product/media/audio/ui/Unlock.ogg</string>
<string name="def_trusted_sound" translatable="false">/product/media/audio/ui/Trusted.ogg</string>
<string name="def_wireless_charging_started_sound" translatable="false">/product/media/audio/ui/WirelessChargingStarted.ogg</string>
<string name="def_charging_started_sound" translatable="false">/product/media/audio/ui/ChargingStarted.ogg</string>
存储默认值/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
例如:loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
存储安全等级可选择system global secure
第二种 新增铃声种类,这种方式可以使用上述“关于系统默认资源文件修改操作”方式添加默认资源文件并存储。
这里说一种参考ringtone设置来电铃声闹铃的默认存储方式/frameworks/base/media/java/android/media/RingtoneManager.java
网上有一些关于电铃声闹铃的默认扫描存储代码流程,但几乎都是Android11之前的mediaScan类说明,根据其提供的代码文件查找会发现都被删除或启用,本文是依据Android11的代码进行说明
关键方法ensureDefaultRingtones()方法
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
public static void ensureDefaultRingtones(@NonNull Context context) {
for (int type : new int[] {
TYPE_RINGTONE,
TYPE_NOTIFICATION,
TYPE_ALARM,
TYPE_OTHER,//新增铃声类型,其需要全局对象配置
}) {
// Skip if we've already defined it at least once, so we don't
// overwrite the user changing to null
final String setting = getDefaultRingtoneSetting(type);
if (Settings.System.getInt(context.getContentResolver(), setting, 0) != 0) {
continue;
}
// Try finding the scanned ringtone
final String filename = getDefaultRingtoneFilename(type);
final Uri baseUri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
try (Cursor cursor = context.getContentResolver().query(baseUri,
new String[] { MediaColumns._ID },
MediaColumns.DISPLAY_NAME + "=?",
new String[] { filename }, null)) {
if (cursor.moveToFirst()) {
final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse(
ContentUris.withAppendedId(baseUri, cursor.getLong(0)));
//设置默认的铃声值,这里说个区别为什么得到的uri是content://开头的原因,而不是绝对路径/product/media/audio/alarms/Alarm_Rooster_02.ogg
//上述有特殊说明,当新增存储时需要setActualDefaultRingtoneUri方法中进行屏蔽
RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
Settings.System.putInt(context.getContentResolver(), setting, 1);
}
}
}
}
private static String getDefaultRingtoneSetting(int type) {
switch (type) {
case TYPE_RINGTONE: return "ringtone_set";
case TYPE_NOTIFICATION: return "notification_sound_set";
case TYPE_ALARM: return "alarm_alert_set";
case TYPE_OTHER: return "sound_timer_set";
default: throw new IllegalArgumentException();
}
}
//该方法获取上述.mk中配置的默认值,然后根据文件名称去数据库中查找对应的uri*****ro.config.ringtone=Ring_Synth_04.ogg
private static String getDefaultRingtoneFilename(int type) {
switch (type) {
case TYPE_RINGTONE: return SystemProperties.get("ro.config.ringtone");
case TYPE_NOTIFICATION: return SystemProperties.get("ro.config.notification_sound");
case TYPE_ALARM: return SystemProperties.get("ro.config.alarm_alert");
//这里直接使用了alerm的默认铃声,若是你需要其他默认铃声,可根据自己的具体需求提供路径文件名称
case TYPE_OTHER: return SystemProperties.get("ro.config.alarm_alert");
default: throw new IllegalArgumentException();
}
}