androidnullpointerexceptionpreferenceactivitysetcontentviewandroid-8.0-oreo

setContentView Causes crash in PreferenceActivity on Android 8.0


My code is pretty simple.

public class SettingsMenuNew extends PreferenceActivity
{
    ...

    @Override
    public void onBuildHeaders(List<Header> target)
    {
        if(!getResources().getBoolean(R.bool.tablet)) {
            setContentView(R.layout.preference_no_buttons);
        }

        loadHeadersFromResource(R.xml.settings_menu, target);
    }
    ....
}

preference_no_buttons.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">

    <include
        layout="@layout/settings_toolbar"
        android:id="@+id/toolbar" />
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

settings_toolbar.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:title="@string/Settings"
    app:titleTextColor="@color/menuWhite"/>

The ... are other methods that are overridden, but just implement the super.<method>() (And isValidFragment which seems to work properly)

Basically, if the device isn't a tablet device, it loads a toolbar for the PreferenceActivity.

This code works fine on all devices except those running Android 8.0. On 8.0 I get the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewGroup.setLayoutTransition(android.animation.LayoutTransition)' on a null object reference

Full Error message:

16507/<myApp> E/AndroidRuntime: FATAL EXCEPTION: main
Process: <myApp>, PID: 16507

java.lang.RuntimeException: Unable to start activity ComponentInfo{<myApp>/<myApp>.SettingsMenuNew}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewGroup.setLayoutTransition(android.animation.LayoutTransition)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewGroup.setLayoutTransition(android.animation.LayoutTransition)' on a null object reference
at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:653)
at <myApp>.SettingsMenuNew.onCreate(SettingsMenuNew.java:33)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
at android.app.ActivityThread.-wrap11(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
at android.os.Handler.dispatchMessage(Handler.java:105) 
at android.os.Looper.loop(Looper.java:164) 
at android.app.ActivityThread.main(ActivityThread.java:6541) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

This error occurs after the onCreate() method runs, but taking out the line setContentView(R.layout.preference_no_buttons); fixes the crash. I have tried moving this code to other methods (onCreate and onPostCreate) but I still get the same error. Does anyone know how to fix this error? Again, it's only happening on Android 8.0. All other versions handle it properly. It also works properly on a tablet device (even a tablet running 8.0, because the offending code is never run in that scenario.)

For now I've just changed if(!getResources().getBoolean(R.bool.tablet)) to if(!getResources().getBoolean(R.bool.tablet) && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) to avoid loading the toolbar on Android O, but a fix which doesn't involve removing the toolbar would be nice.


Solution

  • According to Google, this is the intended behavior, even though it worked properly in previous versions of Android: https://issuetracker.google.com/issues/36873126

    After doing some more reading, I found that PreferenceActivity shouldn't be used for devices using a version of Android later than 3.0.

    Since I am not supporting devices lower and Android 4.0 I have since changed my PreferenceActivity into a plain Activity which uses a PreferenceFragment as described here: https://developer.android.com/guide/topics/ui/settings.html