設定画面のonCreateメソッドでNoSuchMethodExceptionが発生するときの対処方法 | Androidアプリ開発

※当サイトはアフィリエイト広告を利用しています。

Androidの設定画面(PreferenceFragmentCompat)において、onCreateメソッドでNoSuchMethodExceptionが発生するときの対処方法を紹介します。
スポンサーリンク


現象

「現象」というセクションタイトルにしたところすみませんが、私のSharp AQUOSのスマホではこの現象が再現せず、直接の現象の挙動は不明です。

しかし、FirebaseのCrashlytics上にはたしかにonCreateメソッドがNoSuchMethodExceptionの発生を確認できます。

また、この現象が発生するの非常に限られたデバイスのようです。数万人のユーザがいるアプリのCrashlyticsでも以下のデバイスしかありません(数万人のユーザ中20-30人程度の発生率です)。
なぜかSamsung Galaxyの発生率が高いようです。

また、OSのバージョンも新しいデバイスが発生しやすいようです。

原因の推測

以下はAndroid Studioで設定画面Activityを生成したときのコードです。
public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings_activity);
        if (savedInstanceState == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.settings, new SettingsFragment())
                    .commit();
        }
    }

    public static class SettingsFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey);
        }
    }
}

onCreateメソッドでNoSuchMethodExceptionが発生するということは引数であるsavedInstanceStateにおかしな値が入っていることが推測されます。おそらくそれが原因であると考えています。

なお、savedInstanceStateの意味については以下のページがよくまとまっていてオススメです。
https://qiita.com/wbspry/items/c6e342a9008bebef75bd

対処方法

対処方法としてはsavedInstanceStateに異常な値が入っている可能性があるので、強制的にnull(Activity初期生成時と同等)で置き換えてあげればOKです。

以下がサンプルコードです。
public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        savedInstanceState = null;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings_activity);
        if (savedInstanceState == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.settings, new SettingsFragment())
                    .commit();
        }
    }

    public static class SettingsFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey);
        }
    }
}

super.onCreate(savedInstanceState)が呼び出されるまでに、強制的にsavedInstanceStateにnullをセットします(5行目)。

一応、この対処をしてからFirebase crashlyticsでこのエラーが発生することはなくなっています。

まとめ

Androidの設定画面(PreferenceFragmentCompat)において、onCreateメソッドでNoSuchMethodExceptionが発生するときの対処方法を紹介しました。