AndroidQ(10.0) 默认铃声修改

简介: AndroidQ(10.0) 默认铃声修改

Q 版本之前修改方法


新增预制铃声文件至 frameworks/base/data/sounds/ringtones/ogg/ 目录,注意文件格式为 .ogg

编译时拷贝文件至 out 中


frameworks/base/data/sounds/AllAudio.mk

LOCAL_PATH := frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
    $(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
    $(LOCAL_PATH)/ringtones/ogg/ring1.ogg:system/media/audio/ringtones/ring1.ogg \
    $(LOCAL_PATH)/ringtones/ogg/ring2.ogg:system/media/audio/ringtones/ring2.ogg \
    $(LOCAL_PATH)/ringtones/ogg/ring3.ogg:system/media/audio/ringtones/ring3.ogg \
  ....


设置默认铃声为 ring3, 替换原来 Ring_Synth_04.ogg

build/make/target/product/full_base.mk

 # Additional settings used in all AOSP builds
 PRODUCT_PROPERTY_OVERRIDES := \
-    ro.config.ringtone=Ring_Synth_04.ogg \
+    ro.config.ringtone=ring3.ogg \
     ro.config.notification_sound=pixiedust.ogg

最终编译后将写入到 default.prop 文件中

通过 adb 命令可以查看默认值

默认铃声

adb shell getprop ro.config.ringtone

ring1.ogg

默认通知声

adb shell getprop ro.config.notification_sound

OnTheHunt.ogg

默认闹钟声

adb shell getprop ro.config.alarm_alert

Alarm_Classic.ogg

资源文件对应URI

adb shell settings get system ringtone/notification_sound/alarm_alert

content://media/internal/audio/media/200


Q 版本修改方法


Q 版本编译后系统中是没有默认铃声的,也就是没有设置对应值,按照之前方法修改并未生效

搜索 ro.config.ringtone 发现有一堆地方,显然都不是这些,如果是那就会有默认铃声


./build/make/target/product/mainline.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./build/make/target/product/gsi_common.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./build/make/target/product/full_base.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./packages/services/Car/car_product/build/car.mk:    ro.config.ringtone=Girtab.ogg \
./device/generic/goldfish/sdk_phone_x86_vendor.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./device/generic/armv7-a-neon/mini_common.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./device/google/bonito/aosp_sargo.mk:    ro.config.ringtone=Ring_Synth_04.ogg \
./device/google/bonito/aosp_bonito.mk:    ro.config.ringtone=Ring_Synth_04.ogg \


修改位置

build/make/target/product/handheld_system.mk

PRODUCT_PROPERTY_OVERRIDES += \
    ro.carrier=unknown \
+    ro.config.ringtone=ring3.ogg \
    ro.config.notification_sound=OnTheHunt.ogg \
    ro.config.alarm_alert=Alarm_Classic.ogg


预制文件位置不变, system 分区需要改为 product

frameworks/base/data/sounds/AllAudio.mk

LOCAL_PATH := frameworks/base/data/sounds
PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/newwavelabs/Noises3.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/Noises3.ogg \
     $(LOCAL_PATH)/newwavelabs/OrganDub.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/OrganDub.ogg \
     $(LOCAL_PATH)/ringtones/ogg/Orion.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/Orion.ogg \
+    $(LOCAL_PATH)/ringtones/ogg/ring1.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/ring1.ogg \
+    $(LOCAL_PATH)/ringtones/ogg/ring2.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/ring2.ogg \
+    $(LOCAL_PATH)/ringtones/ogg/ring3.ogg:$(TARGET_COPY_OUT_PRODUCT)/media/audio/ringtones/ring3.ogg \
  ....


简单看下流程


上面说到的通过 adb 指令可以获取对应资源值,系统播放最终对应的都是资源URI,也就对应着数据库

frameworks\base\media\java\android\media\MediaScanner.java

MediaScanner 读取 ro.config.ringtone 值后组装成 URI 写入 Settings.system 数据库

 /** The filename for the default sound for the ringer ringtone. */
    @UnsupportedAppUsage
    private String mDefaultRingtoneFilename;
 private static final String DEFAULT_RINGTONE_PROPERTY_PREFIX = "ro.config.";
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);
}
 // Setting a flag in order not to use bulk insert for the file related with
// notifications, ringtones, and alarms, because the rowId of the inserted file is
// needed.
else if (ringtones && !mDefaultRingtoneSet) {
    if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
            doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
        needToSetSettings = true;
    }
}
if(needToSetSettings) {
    if (notifications) {
        setRingtoneIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
        mDefaultNotificationSet = true;
    } else if (ringtones) {
        setRingtoneIfNotSet(Settings.System.RINGTONE, 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);
        }

RingtoneManager 中从 Settings.system 读取指定类型对应的URI

frameworks\base\media\java\android\media\RingtoneManager.java

public static Uri getActualDefaultRingtoneUri(Context context, int type) {
        String setting = getSettingForType(type);
        if (setting == null) return null;
        final String uriString = Settings.System.getStringForUser(context.getContentResolver(),
                setting, context.getUserId());
        Uri ringtoneUri = uriString != null ? Uri.parse(uriString) : null;
        // If this doesn't verify, the user id must be kept in the uri to ensure it resolves in the
        // correct user storage
        if (ringtoneUri != null
                && ContentProvider.getUserIdFromUri(ringtoneUri) == context.getUserId()) {
            ringtoneUri = ContentProvider.getUriWithoutUserId(ringtoneUri);
        }
        return ringtoneUri;
    }
  private static String getSettingForType(int type) {
        if ((type & TYPE_RINGTONE) != 0) {
            return Settings.System.RINGTONE;
        } else if ((type & TYPE_NOTIFICATION) != 0) {
            return Settings.System.NOTIFICATION_SOUND;
        } else if ((type & TYPE_ALARM) != 0) {
            return Settings.System.ALARM_ALERT;
        } else {
            return null;
        }
    }


Settings 中声音界面获取默认值对应名称显示


vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\notification\RingtonePreferenceControllerBase.java

 private void updateSummary(Preference preference) {
        final Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(
                mContext, getRingtoneType());
         final CharSequence summary = getSummary(ringtoneUri);
        if (summary != null) {
            ThreadUtils.postOnMainThread(() -> preference.setSummary(summary));
        }
    }
private CharSequence getSummary(Uri ringtoneUri) {
         CharSequence summary = null;
         try {
           summary = Ringtone.getTitle(
           mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
           return summary;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

Ringtone 中 getTitle 解析获取对应文本名称

frameworks\base\media\java\android\media\Ringtone.java


public static String getTitle(
            Context context, Uri uri, boolean followSettingsUri, boolean allowRemote) {
        ContentResolver res = context.getContentResolver();
        String title = null;
        if (uri != null) {
            String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
            if (Settings.AUTHORITY.equals(authority)) {
                if (followSettingsUri) {
                    Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context,
                            RingtoneManager.getDefaultType(uri));
                    String actualTitle = getTitle(
                            context, actualUri, false /*followSettingsUri*/, allowRemote);
                    title = context
                            .getString(com.android.internal.R.string.ringtone_default_with_actual,
                                    actualTitle);
                }
            } else {
                Cursor cursor = null;
                try {
                    if (MediaStore.AUTHORITY.equals(authority)) {
                        final String mediaSelection = allowRemote ? null : MEDIA_SELECTION;
                        cursor = res.query(uri, MEDIA_COLUMNS, mediaSelection, null, null);
                        if (cursor != null && cursor.getCount() == 1) {
                            cursor.moveToFirst();
                            return cursor.getString(1);
                        }
                        // missing cursor is handled below
                    }
                } catch (SecurityException e) {
                    IRingtonePlayer mRemotePlayer = null;
                    if (allowRemote) {
                        AudioManager audioManager =
                                (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                        mRemotePlayer = audioManager.getRingtonePlayer();
                    }
                    if (mRemotePlayer != null) {
                        try {
                            title = mRemotePlayer.getTitle(uri);
                        } catch (RemoteException re) {
                        }
                    }
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                    cursor = null;
                }
                if (title == null) {
                    title = uri.getLastPathSegment();
                }
            }
        } else {
            title = context.getString(com.android.internal.R.string.ringtone_silent);
        }
        if (title == null) {
            title = context.getString(com.android.internal.R.string.ringtone_unknown);
            if (title == null) {
                title = "";
            }
        }
        return title;
    }


目录
相关文章
|
7月前
|
Java Android开发
Android系统 修改无源码普通应用为默认Launcher和隐藏Settings中应用信息图标
Android系统 修改无源码普通应用为默认Launcher和隐藏Settings中应用信息图标
947 0
|
5月前
解除谷歌浏览器默认禁止音频自动播放
解除谷歌浏览器默认禁止音频自动播放
90 1
|
7月前
Win11关闭时间显示——强行修改右下角时间显示
Win11关闭时间显示——强行修改右下角时间显示
262 1
|
C++ Windows
设置软件的默认打开方式
设置软件的默认打开方式
设置软件的默认打开方式
|
数据库
默认输入法删除后无法自动切换到新输入法
默认输入法删除后无法自动切换到新输入法
582 0
【PhpStorm】取消参数前的类型显示
【PhpStorm】取消参数前的类型显示
176 0
【PhpStorm】取消参数前的类型显示