Search code examples
androidandroid-studioandroid-layoutandroid-fragmentsandroidx

Setting Activity crashing while launching in android 10 works well in android 28<. How to fix it?


I have an activity which contains settings. After launching SettingsActivity.java its crashing. It works well when tested in physical device i.e, API 19, API23, API26. I'm facing this issue only in API 29. What is the cause for this problem & How to fix it? refer to the code below

SettingActivity.java

package ak.wp.meto.activity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuItem;
import android.widget.Toast;
import java.io.File;

public class SettingsActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
        initToolbar();
    }

    private void initView() {
        setContentView(R.layout.activity_settings);

        // replace linear layout by preference screen
        getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();
    }

    private void initToolbar() {
        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setTitle(getString(R.string.settings));

    }

    @SuppressLint("ValidFragment")
    public class MyPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.settings_preference);
            // clears web cache
            final CheckBoxPreference clr_webcache = (CheckBoxPreference) getPreferenceManager().findPreference("perf_cache_clr");
            clr_webcache.setChecked(false);
            clr_webcache.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    Toast.makeText(getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();
                    try {
                        trimCache(getActivity());
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return true;
                }
            });
        }

        private void trimCache(Context context) {

            try {
                File dir = context.getCacheDir();
                if (dir != null && dir.isDirectory()) {
                    deleteDir(dir);
                }
            } catch (Exception e) {
                // TODO: handle exception
            }

        }

        private boolean deleteDir(File dir) {

            if (dir != null && dir.isDirectory()) {
                String[] children = dir.list();
                for (int i = 0; i < children.length; i++) {
                    boolean success = deleteDir(new File(dir, children[i]));
                    if (!success) {
                        Toast.makeText(getApplicationContext(),"FAILED:Try clearing using device settings",Toast.LENGTH_SHORT).show();
                        return false;
                    }else{
                        Toast.makeText(getApplicationContext(),"SUCCESS: CACHE CLEARED",Toast.LENGTH_SHORT).show();
                    }
                }
            }
            // The directory is now empty so delete it
            return dir.delete();
        }
        //END OF MYPREFERENCE FRAGMENT
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }
}

This is my activity_settings.xml

activity_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/toolbarTop"
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbarTop"
        android:orientation="horizontal" />

</RelativeLayout>

This is my setting_preference.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference
        android:key="perf_notification"
        android:title="@string/pref_notification_title"
        android:summary="@string/pref_notification_summ"
        android:defaultValue="true" />


    <ListPreference
        android:key="pref_font_size"
        android:title="@string/pref_text_title"
        android:dialogTitle="@string/select_size"
        android:entries="@array/text_entries"
        android:entryValues="@array/text_entries"
        android:defaultValue="@string/default_text" />


    <CheckBoxPreference
        android:key="perf_cache_clr"
        android:title="Clear Cache"
        android:summary="Deletes Cache to Load Latest Updates "
        android:defaultValue="false" />

</PreferenceScreen>

Logcat says fatal exception in SettingsActivity.java in line 28 & 36 LOGCAT

2020-10-23 11:24:23.025 19845-19845/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ak.wp.meto, PID: 19845
    java.lang.RuntimeException: Unable to start activity ComponentInfo{ak.wp.meto/ak.wp.meto.activity.SettingsActivity}: java.lang.IllegalStateException: Fragment ak.wp.meto.activity.SettingsActivity.MyPreferenceFragment must be a public static class to be  properly recreated from instance state.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3632)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3784)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2270)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8125)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: java.lang.IllegalStateException: Fragment ak.wp.meto.activity.SettingsActivity.MyPreferenceFragment must be a public static class to be  properly recreated from instance state.
        at android.app.BackStackRecord.doAddOp(BackStackRecord.java:429)
        at android.app.BackStackRecord.replace(BackStackRecord.java:470)
        at android.app.BackStackRecord.replace(BackStackRecord.java:462)
        at ak.wp.meto.activity.SettingsActivity.initView(SettingsActivity.java:36)
        at ak.wp.meto.activity.SettingsActivity.onCreate(SettingsActivity.java:28)
        at android.app.Activity.performCreate(Activity.java:7957)
        at android.app.Activity.performCreate(Activity.java:7946)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3607)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3784) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2270) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:8125) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

I'm having ERROR in line 36

getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();

In turn gave ERROR for function initView() line 28

KIndly help me to sort out this issue


Solution

  • BINGO, I solved it!!! Finally, this worked for me: I made MyPreferenceFragment to static class

    public static class MyPreferenceFragment extends PreferenceFragment 
    

    The second problem was Toast.makeText giving out ERROR saying to make MyPreferenceFragment not static. So I replaced Toast by

    Toast.makeText(getActivity().getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();
    

    Thank You guys for your support.