我即将启动我的应用程序的更新,但遇到了一个问题。
其中一个首选项类已从 CheckBox 更改为 Switch,现在以前安装该应用程序的用户在尝试访问 PreferenceActivity 时遇到了崩溃。
这是我的堆栈跟踪:
2021-12-03 19:42:51.824 18764-18764/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: xxx.xxx.xxx, PID: 18764
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
at android.app.SharedPreferencesImpl.getBoolean(SharedPreferencesImpl.java:331)
at androidx.preference.Preference.getPersistedBoolean(Preference.java:1955)
at androidx.preference.TwoStatePreference.onSetInitialValue(TwoStatePreference.java:201)
at androidx.preference.Preference.onSetInitialValue(Preference.java:1614)
at androidx.preference.Preference.dispatchSetInitialValue(Preference.java:1587)
at androidx.preference.Preference.onAttachedToHierarchy(Preference.java:1311)
at androidx.preference.Preference.onAttachedToHierarchy(Preference.java:1326)
at androidx.preference.PreferenceGroup.addPreference(PreferenceGroup.java:249)
at androidx.preference.PreferenceGroup.addItemFromInflater(PreferenceGroup.java:170)
at androidx.preference.PreferenceInflater.rInflate(PreferenceInflater.java:345)
at androidx.preference.PreferenceInflater.rInflate(PreferenceInflater.java:346)
at androidx.preference.PreferenceInflater.inflate(PreferenceInflater.java:157)
at androidx.preference.PreferenceInflater.inflate(PreferenceInflater.java:109)
at androidx.preference.PreferenceManager.inflateFromResource(PreferenceManager.java:216)
at androidx.preference.PreferenceFragmentCompat.addPreferencesFromResource(PreferenceFragmentCompat.java:361)
at xxx.xxx.xxx.ui.activities.settings.SettingsActivity$SettingsFragment.onCreatePreferences(SettingsActivity.java:164)
at androidx.preference.PreferenceFragmentCompat.onCreate(PreferenceFragmentCompat.java:160)
at xxx.xxx.xxx.ui.activities.settings.SettingsActivity$SettingsFragment.onCreate(SettingsActivity.java:149)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2949)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:475)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1440)
at android.app.Activity.performStart(Activity.java:8109)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3806)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:235)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:215)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:187)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:105)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
问题是,以前,CheckBox 值是字符串格式,所以现在它们被迁移到布尔值,当尝试获取设置值时会崩溃。
不幸的是,StackTrace 没有给我有用的信息,因为它在 onCreate 而不是在特定行中崩溃。
我尝试在启动时清除所有 SwitchPreference 值无济于事:
//clear switch preferences
SharedPreferences prefs = TMPreferences.getPrefs();
prefs.edit().remove("SHUFFLE").apply();
prefs.edit().remove("NOTIFICATIONS_RANDOMNOTIFICATIONS").apply();
prefs.edit().remove("VIDEORECOMMENDATION").apply();
//set switch preferences
prefs.edit().putBoolean("SHUFFLE", false).apply();
prefs.edit().putBoolean("NOTIFICATIONS_RANDOMNOTIFICATIONS", false).apply();
prefs.edit().putBoolean("VIDEORECOMMENDATION", false).apply();
我知道一种解决方案是“强制”用户转到“应用程序”>“清除应用程序数据”,但不想结束这样做。
我期望的是一种方法来重置旧的 CheckBoxes 值并用新的 SwitchPreferences 替换它们,而不要求使用来清除数据。
对于新用户,该应用程序运行良好。
这是我的 Preferences.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="pref_category_test"
android:title="@string/pref_category_test"
app:iconSpaceReserved="false">
<ListPreference
android:key="pref_testtime"
android:title="@string/pref_testtime"
android:entries="@array/testtime_texts"
android:entryValues="@array/testtime_values"
android:defaultValue="-1"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_shuffle"
android:title="@string/pref_shuffle"
android:defaultValue="false"
app:iconSpaceReserved="false" />
<ListPreference
android:key="pref_fontsize"
android:title="@string/pref_fontsize"
android:entries="@array/fontsize_texts"
android:entryValues="@array/fontsize_values"
android:defaultValue="100"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_language"
android:title="@string/pref_category_language"
app:iconSpaceReserved="false">
<ListPreference
android:key="pref_languages"
android:title="@string/pref_language"
android:entries="@array/language_texts"
android:entryValues="@array/language_values"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_notification"
android:title="@string/pref_category_notifications"
app:iconSpaceReserved="false">
<ListPreference
android:key="pref_notifications_interval"
android:title="@string/pref_taketest_reminder"
android:entries="@array/notification_texts"
android:entryValues="@array/notification_values"
android:defaultValue="1"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_notifications_randomnotifications"
android:title="@string/pref_randomnotifications"
android:defaultValue="false"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_videorecommendation"
android:title="@string/pref_videorecommendation_notification"
android:defaultValue="true"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_checkfornewtests"
android:title="@string/pref_checkfornewtests_notification"
android:defaultValue="true"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_aspect"
android:title="@string/pref_category_aspect"
app:iconSpaceReserved="false">
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_animation"
android:title="@string/pref_category_animations"
app:iconSpaceReserved="false">
<SwitchPreference
android:key="pref_transitionanimation"
android:title="@string/pref_transitionanimation"
android:defaultValue="true"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_sounds"
android:title="@string/pref_category_sounds"
app:iconSpaceReserved="false">
<SwitchPreference
android:key="pref_buttonsound"
android:title="@string/pref_buttonsound"
android:defaultValue="false"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_pageflipsound"
android:title="@string/pref_pageflipsound"
android:defaultValue="false"
app:iconSpaceReserved="false" />
<SwitchPreference
android:key="pref_endtestsound"
android:title="@string/pref_endtestsound"
android:defaultValue="false"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_users"
android:title="@string/pref_category_users"
app:iconSpaceReserved="false">
<Preference
android:key="pref_loggedinas"
android:title="@string/activitypreferences_loggedinas"
app:iconSpaceReserved="false">
</Preference>
<Preference
android:key="pref_deletecurrentuser"
android:title="@string/activitypreferences_deletecurrentuser"
app:iconSpaceReserved="false">
</Preference>
<Preference
android:key="pref_changemypassword"
android:title="@string/activitypreferences_changemypassword"
app:iconSpaceReserved="false">
</Preference>
</PreferenceCategory>
<PreferenceCategory
android:key="pref_category_troubleshooting"
android:title="@string/pref_category_troubleshooting"
app:iconSpaceReserved="false">
<Preference
android:key="pref_resyncalldata"
android:title="@string/activitypreferences_resyncalldata"
app:iconSpaceReserved="false">
</Preference>
</PreferenceCategory>
</PreferenceScreen>
SettingsActivity onCreate:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}