android - RingtonePreference 无法在 android 8.1 上添加新铃声
问题描述
在 xml 文件中,我有以下代码。我可以通过单击 ringtonepref 屏幕中的广告铃声按钮来选择 mp3 声音,但是当我这样做时,我看到以下异常。这以前可以工作,但在更新到 android 8 之后就不能工作了。
怎么能
<RingtonePreference
android:defaultValue="content://settings/system/notification_sound"
android:key="ringtone_pref"
android:ringtoneType="all"
android:title="@string/hr_beep_tone_title"
android:summary="@string/hr_beep_tone_summary"/>
01-17 00:21:15.785 15503-16432/? E/RingtonePickerActivity: Unable to add new ringtone
java.lang.IllegalArgumentException: Unsupported ringtone type: 7
at android.media.RingtoneManager.getExternalDirectoryForType(RingtoneManager.java:1088)
at android.media.RingtoneManager.addCustomExternalRingtone(RingtoneManager.java:1056)
at com.android.providers.media.RingtonePickerActivity$2.doInBackground(RingtonePickerActivity.java:281)
at com.android.providers.media.RingtonePickerActivity$2.doInBackground(RingtonePickerActivity.java:278)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
解决方案
挖了android-27源码,好像addCustomExternalRingtone
是在复制你选择的声音文件,但是给定的参数TYPE_ALL
是不允许确定要保存的目录的。
addCustomExternalRingtone
@WorkerThread
public Uri addCustomExternalRingtone(@NonNull final Uri fileUri, final int type)
throws FileNotFoundException, IllegalArgumentException, IOException {
...
// Choose a directory to save the ringtone. Only one type of installation at a time is
// allowed. Throws IllegalArgumentException if anything else is given.
final String subdirectory = getExternalDirectoryForType(type);
// Find a filename. Throws FileNotFoundException if none can be found.
final File outFile = Utils.getUniqueExternalFile(mContext, subdirectory,
Utils.getFileDisplayNameFromUri(mContext, fileUri), mimeType);
// Copy contents to external ringtone storage. Throws IOException if the copy fails.
try (final InputStream input = mContext.getContentResolver().openInputStream(fileUri);
final OutputStream output = new FileOutputStream(outFile)) {
Streams.copy(input, output);
}
// Tell MediaScanner about the new file. Wait for it to assign a {@link Uri}.
try (NewRingtoneScanner scanner = new NewRingtoneScanner(outFile)) {
return scanner.take();
} catch (InterruptedException e) {
throw new IOException("Audio file failed to scan as a ringtone", e);
}
}
并且getExternalDirectoryForType
,实际发生错误的地方。
private static final String getExternalDirectoryForType(final int type) {
switch (type) {
case TYPE_RINGTONE:
return Environment.DIRECTORY_RINGTONES;
case TYPE_NOTIFICATION:
return Environment.DIRECTORY_NOTIFICATIONS;
case TYPE_ALARM:
return Environment.DIRECTORY_ALARMS;
default:
throw new IllegalArgumentException("Unsupported ringtone type: " + type);
}
}
问题是RingtonePickerActivity
无法决定选择哪种类型进行保存,最后给出TYPE_ALL。
看来您应该覆盖选择文件的点,并将 uri 和 type 传递给RingtoneManager.addCustomExternalRingtone
,或者自己保存文件。
推荐阅读
- html - 使用材质 ui svg 图标作为背景图片
- java - 如何在 InDesign Java 文档中获得真实的页数
- matlab - 如何将二进制函数应用于元胞数组和双精度数组
- go - Golang - 如何从代码内部显示模块版本
- c++ - 在 Windows 上打开的 C++ 文件总是失败
- binding - 我可以在我的 CollectionView 中使用填充视图的 ItemsSource 列表之外的值填充标签吗?
- javascript - Flask:javascript读取时python对象到json触发错误
- javascript - SELECT WITH CAST OR CONVERT IN iLike 使用 SEQUELIZE
- javascript - JavaScript 解释器如何知道遇到的函数调用应该同步处理还是异步处理?
- node.js - 如何从nodejs中的http请求保存缓存状态?