如何从代码中设置RingtonePreference值?

6

我有以下的偏好:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
   <RingtonePreference
    android:showDefault="true"
    android:showSilent="true"
    android:title="@string/feed_alert_ringtone"
    android:ringtoneType="ringtone|notification|alarm|all"
    android:key="alertringtone"
    android:persistent="false">
   </RingtonePreference>     
</PreferenceScreen>

当用户更改此首选项时,我会手动将Uri保存到数据库中:
public boolean onPreferenceChange(Preference pref, Object change) {
    String ringtone = change.toString();

    // save it to a db
    ...

    return true;
}

我的问题是,当用户关闭并重新进入“PreferenceScreen”时,“RingtonePreference”的默认值始终为“Silence”。当然,我必须手动设置该值。
我在我的“PreferenceActivity”中尝试了这个方法:
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.settings); // the XML above

    String database_ringtone = ... // get the string saved above from db
                                   // and according to some parameters passed
                                   // to the intent

    Preference ringtone = findPreference("alertringtone");
    ringtone.setDefaultValue( database_ringtone );

    // also tried:
    ringtone.setDefaultValue( Uri.parse(database_ringtone) );
}

很不幸,喜好仍保持为“静音”(表示为空)。我认为,当Preference不是persistent时,将使用默认值。

我无法使其persistent,因为偏好用于多个项目,并且从DB获取的数据根据传递给意图的一些额外数据而变化。

尽管如此,我不想设置默认值,而是要设置从数据库中获取的当前值。我认为这可能是一个解决方法。所以任何其他方式也可以。

已经双重检查了保存和从DB检索是否正常工作,所以那不是问题。

我如何从代码中设置RingtonePreference值?


编辑:这里有一个小解释,我想做什么,也许还有另一种方法。

我有几个菜单项(数量因用户而异),用户可以为每个菜单项选择铃声。选择铃声使用上面的xml完成,菜单项的ID通过Intent传递到PreferenceActivity中。铃声的URI然后存储在数据库中。

当其中一个条目更改时,会根据用户所做的铃声选择播放警报。因此,他知道哪一个更改了。到目前为止没有问题。

问题在于,当用户想要为已经定义了铃声的条目更改铃声时。如果用户之前选择的铃声是Foo,则在单击RingtonePreference时,应预先选择铃声Foo。这不是什么严重的错误(更像是一个故障),但仍然非常令人恼火。

据我所知,没有办法从代码中预选默认的RingtonePreference吗?还是我做错了?


编辑2:好的,我认为没有办法做到这一点。非常奇怪,Android核心,允许我们使用Preference并从中获取值,但不能将值放回。肯定很匆忙。我很高兴可以用代码检查CheckBoxPreference...

3个回答

6

我在搜索如何设置默认铃声时,发现了和你一样的问题,当首选项没有设置时,值为空,并且静音作为默认选项被选择。但是我做了这个

// I read my ringtone setting (I read the value from my ringtone_uri key)
// then if it is not set I set the value with the default value from the phone
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Uri configuredUri = Uri.parse(sharedPrefs.getString("ringtone_uri", Settings.System.DEFAULT_RINGTONE_URI.toString()));

// then I do this, I save the default ringtone to my settins
if(configuredUri.equals(Settings.System.DEFAULT_RINGTONE_URI)){
    sharedPrefs.edit()
            .putString("ringtone_uri", Settings.System.DEFAULT_RINGTONE_URI.toString())
            .commit();
}

我不知道这是否对你有所帮助,但我希望能帮到其他人。顺便说一句,我在找到这个解决方法时很激动。


虽然我无法理解你的代码(如果已经设置为默认值,为什么要写回默认值?),但是这段代码片段确实展示了如何从代码中写入RingtonePreference。将DEFUALT_RINGTONE_URI替换为DB中的值,你就可以解决OP的问题。而且我不认为这是一个变通方法。 - Nilzor

3

两年后尝试解决完全相同的问题时,发现没有找到好的答案,因此我将发布我的解决方案。

与许多其他首选项不同,RingtonePreference似乎不受调用setDefaultValue()的影响。我尝试了同样的方法,但无法使其正常工作,而对于大多数其他首选项则可以。

我查看了API并找到了RingtonePreference用于存储和恢复状态的一系列回调。特别值得注意的是RingtonePreference.onRestoreState()方法。

因此,当铃声选择器打开时,它会调用此方法来选择所选铃声。为了最初选择铃声,您必须覆盖此方法并返回要选择的URI。

我的解决方案如下

        //Create a Ringtone Preference
        RingtonePreference ringtonePreference = new RingtonePreference(this){
            @Override
            protected Uri onRestoreRingtone(){
                if(database_ringtone.equals("")){
                    return null;
                }
                else{
                    return Uri.parse(database_ringtone);
                }
            }
        };

        ringtonePreference.setTitle(getString(R.string.pref_title_ringtone));
        ringtonePreference.setPersistent(false);

        //Set the summary to the initial value
        BasePreferenceChangeListener.updatePreference(ringtonePreference, agency.ringtone);

        getPreferenceScreen().addPreference(ringtonePreference);

我选择匿名重写该方法,然后手动将偏好设置插入到PreferenceScreen中。
您还可以创建一个RingtonePreference的子类,覆盖该方法,然后在XML中使用该子类而不是RingtonePreference。

-1

看起来在将铃声插入数据库时没有包含音频文件的路径,因此每当您尝试从应用程序设置时,它都会变成“静音”。当您说必须手动设置值时,似乎媒体扫描media/ringtones会捕获音频文件并在那时将其插入数据库。下面的代码需要根据您的方式进行修改,但希望它能给您正确的想法。

尝试类似于:

File k = new File(path2, filename);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());

//kill database for this object before inserting
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);

Uri newUri = getContentResolver().insert(uri, values); 

那不是我所问的答案。选择铃声并将其URI存储到数据库中是有效的(根据所做的选择播放声音也没有问题)。我只想在用户再次打开首选项时通过预先选择铃声来反映我之前所做的选择。我没有添加任何带有特殊路径的自定义铃声。 - Markus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接