You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11系统使用RingtoneManager设置自定义铃声报错求助

错误触发原因
  • Android 11 强制开启分区存储,MediaStore.MediaColumns.DATA 字段已被官方废弃,你代码中通过绝对路径操作MediaStore条目的逻辑不再被系统允许,直接触发文件找不到的ENOENT报错。
  • 铃声类型Uri校验规则变更:Android 11要求设置为铃声的音频必须归属系统铃声对应的MediaStore分类,你代码中使用通用的外部音频Uri插入条目,且文件存放在Music目录,不符合铃声Uri校验规则,抛出Uri不属于铃声、闹钟或通知类型的安全异常。
  • 权限缺失:修改系统铃声需要特殊的WRITE_SETTINGS权限,普通存储权限无法完成该操作。
Android 11 适配方案

步骤1:声明并申请所需权限

首先在AndroidManifest.xml中添加权限声明:

<!-- 安卓10及以下存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<!-- 修改系统设置权限,用于设置铃声 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 安卓13及以上读取音频权限,仅当你需要读取其他应用的音频文件时添加 -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

运行时先判断是否有修改系统设置权限,无权限则跳转系统设置页引导用户开启:

private static final int REQUEST_CODE_WRITE_SETTINGS = 1001;

// 权限校验逻辑
if (!Settings.System.canWrite(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS);
}

步骤2:修改铃声写入逻辑

Android 11及以上版本不要使用DATA字段,也不要用通用的外部音频Uri插入条目,直接通过MediaStore流写入铃声数据:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.TITLE, "ringtonename");
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "ringtonename");
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, getMIMEType(ringtone_file.getPath()));
    contentValues.put(MediaStore.Audio.Media.ARTIST, "ringtonename");
    contentValues.put(MediaStore.Audio.Media.IS_RINGTONE, true);
    contentValues.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
    contentValues.put(MediaStore.Audio.Media.IS_ALARM, true);
    contentValues.put(MediaStore.Audio.Media.IS_MUSIC, false);

    ContentResolver contentResolver = getContentResolver();
    // 直接使用铃声分类的Uri插入
    Uri audioUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    Uri insertUri = contentResolver.insert(audioUri, contentValues);

    if (insertUri != null) {
        // 通过输出流写入音频数据,替换原有直接写绝对路径的逻辑
        OutputStream os = contentResolver.openOutputStream(insertUri);
        FileInputStream fis = new FileInputStream(ringtone_file);
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
        fis.close();
        os.close();
        // 设置默认铃声
        RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, insertUri);
    }
} else {
    // 保留原有Android 10及以下版本的逻辑即可
}

内容的提问来源于stack exchange,提问作者nasser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 20:24:04