设置 Activity 在 android 10 中启动时崩溃在 android 28< 中运行良好。如何解决?
Setting Activity crashing while launching in android 10 works well in android 28<. How to fix it?
我有一个包含设置的 activity。启动 SettingsActivity.java 后崩溃。它在物理设备上测试时效果很好,即 API 19、API23、API26。我只在 API 29 遇到过这个问题。
此问题的原因是什么以及如何解决?参考下面的代码
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();
}
}
这是我的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>
这是我的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 在第 28 和 36 行的 SettingsActivity.java 中表示致命异常
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)
我在第 36 行遇到错误
getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();
依次为函数 initView()
第 28 行
给出了 ERROR
请帮我解决这个问题
您必须创建 SettingsFragment
的实例才能启动它
public static MyPreferenceFragment getInstance() {
MyPreferenceFragment fragment = new MyPreferenceFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
return fragment;
}
并通过调用
替换它
getFragmentManager().beginTransaction().replace(R.id.content, MyPreferenceFragment.getInstance()).commit();
将 Fragment 放入一个单独的文件中,该文件的名称与 Fragment (MyPreferenceFragment.java) 的名称相同。它应该可以解决问题。
同时检查新的 Preference 库。 Android.preference 正在弃用。而不是:
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
使用:
import androidx.fragment.app.Fragment
import androidx.preference.CheckBoxPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
BINGO,我解决了!!!
最后,这对我有用:
我将 MyPreferenceFragment 设为 static
class
public static class MyPreferenceFragment extends PreferenceFragment
第二个问题是 Toast.makeText 发出错误消息说要使 MyPreferenceFragment 不是静态的。所以我用
替换了 Toast
Toast.makeText(getActivity().getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();
谢谢大家的支持。
我有一个包含设置的 activity。启动 SettingsActivity.java 后崩溃。它在物理设备上测试时效果很好,即 API 19、API23、API26。我只在 API 29 遇到过这个问题。 此问题的原因是什么以及如何解决?参考下面的代码
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();
}
}
这是我的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>
这是我的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 在第 28 和 36 行的 SettingsActivity.java 中表示致命异常 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)
我在第 36 行遇到错误
getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();
依次为函数 initView()
第 28 行
请帮我解决这个问题
您必须创建 SettingsFragment
的实例才能启动它
public static MyPreferenceFragment getInstance() {
MyPreferenceFragment fragment = new MyPreferenceFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
return fragment;
}
并通过调用
替换它getFragmentManager().beginTransaction().replace(R.id.content, MyPreferenceFragment.getInstance()).commit();
将 Fragment 放入一个单独的文件中,该文件的名称与 Fragment (MyPreferenceFragment.java) 的名称相同。它应该可以解决问题。
同时检查新的 Preference 库。 Android.preference 正在弃用。而不是:
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
使用:
import androidx.fragment.app.Fragment
import androidx.preference.CheckBoxPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
BINGO,我解决了!!!
最后,这对我有用:
我将 MyPreferenceFragment 设为 static
class
public static class MyPreferenceFragment extends PreferenceFragment
第二个问题是 Toast.makeText 发出错误消息说要使 MyPreferenceFragment 不是静态的。所以我用
替换了 ToastToast.makeText(getActivity().getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();
谢谢大家的支持。