将PreferenceCategory动态添加到PreferenceScreen时遇到错误

时间:2018-03-04 04:57:03

标签: android android-preferences

我目前正计划在我的应用中实施动态通知设置。如果当前设备正在运行Android Oreo,请显示通知频道设置。如果它不是Android Oreo,请显示其他设置(PreferenceCategory

这是我的代码片段,用于在设备的版本不是奥利奥时显示:

for (MyNotificationChannel notificationChannel : notificationChannels) {
    System.out.println("Notification channel created at index " + notificationChannel.getIndex());
    PreferenceCategory preferenceCategory = new PreferenceCategory(preferenceScreen.getContext());
    preferenceCategory.setTitle(notificationChannel.getNotificationTitle());
    preferenceCategory.setSummary(notificationChannel.getNotificationDesc());
    SwitchPreference enableNotificationPreference = new SwitchPreference(preferenceScreen.getContext());
    enableNotificationPreference.setDefaultValue(true);
    enableNotificationPreference.setTitle("Enable notification channel");
    enableNotificationPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            System.out.println("Preference change: " + newValue);
            return true;
        }
    });
    preferenceCategory.addPreference(enableNotificationPreference);
    SwitchPreference enableVibratePreference = new SwitchPreference(preferenceScreen.getContext());
    enableVibratePreference.setTitle("Vibrate");
    enableVibratePreference.setSummary("Whether to vibrate when there are notifications available");
    enableVibratePreference.setDefaultValue(true);
    enableVibratePreference.setIcon(R.drawable.ic_vibrate_white_24dp);
    enableVibratePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            System.out.println("Preference change: " + newValue);
            return true;
        }
    });
    RingtonePreference notificationRingtonePreference = new RingtonePreference(preferenceScreen.getContext());
    notificationRingtonePreference.setIcon(R.drawable.ic_music_white_24dp);
    notificationRingtonePreference.setTitle("Set ringtone");
    bindPreferenceSummaryToValue(notificationRingtonePreference);
    preferenceCategory.addPreference(notificationRingtonePreference);
    preferenceScreen.addPreference(preferenceCategory);
}

(顺便说一下,MyNotificationChannel只是一个类,用作我的通知设置的界面,以便更轻松地从strings.xml获取内容

但是,当我尝试导航到通知片段时,我收到此错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'long android.preference.PreferenceManager.getNextId()' on a null object reference
  at android.preference.Preference.onAttachedToHierarchy(Preference.java:1326)
  at android.preference.PreferenceGroup.addPreference(PreferenceGroup.java:163)
  at com.edricchan.studybuddy.SettingsActivity$NotificationPreferenceFragment.onCreate(SettingsActivity.java:345)
  at android.app.Fragment.performCreate(Fragment.java:2489)
  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1237)
  at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2407)
  at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2186)
  at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2142)
  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2043)
  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:719)
  at android.os.Handler.handleCallback(Handler.java:790)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:164)
  at android.app.ActivityThread.main(ActivityThread.java:6494)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

编辑:这是我的偏好文件:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This preference screen will be filled in via code -->
</PreferenceScreen>

编辑#2:当我恢复到原来的实现时(对于Android Oreo),它可以工作:

PreferenceCategory notificationPrefCategory = new PreferenceCategory(preferenceScreen.getContext());
notificationPrefCategory.setTitle("Notification Channels");
preferenceScreen.addPreference(notificationPrefCategory);
Preference allNotificationsPreference = new Preference(preferenceScreen.getContext());
allNotificationsPreference.setTitle(R.string.notification_channel_all_channels_title);
allNotificationsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            intent.putExtra(Settings.EXTRA_APP_PACKAGE, getActivity().getPackageName());
            startActivity(intent);
        }
        return false;
    }
});
notificationPrefCategory.addPreference(allNotificationsPreference);
for (MyNotificationChannel notificationChannel : notificationChannels) {
    Preference notificationPreference = new Preference(preferenceScreen.getContext());
    notificationPreference.setTitle(notificationChannel.getNotificationTitle());
    notificationPreference.setSummary(notificationChannel.getNotificationDesc());
    notificationPreference.setKey(notificationChannelIds[notificationChannel.getIndex()]);
    notificationPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
        @Override
        public boolean onPreferenceClick(Preference preference) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, getActivity().getPackageName());
                intent.putExtra(Settings.EXTRA_CHANNEL_ID, preference.getKey());
                startActivity(intent);
            }
            return false;
        }
    });
    notificationPrefCategory.addPreference(notificationPreference);
}

1 个答案:

答案 0 :(得分:1)

我在定义所有其他首选项之前,通过将首选项类别添加到首选项屏幕的行向上移动来修复此问题:

// This line
preferenceScreen.addPreference(preferenceCategory);

(P.S。我在定义PreferenceCategory)之后把它移到了