AndroidManifest.xml设置如下,但开机后发现onCreate被执行了两次

<activity
    android:name="....Activity***"
    <intent-filter>
        <category android:name="android.intent.category.HOME" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

原因是系统配置发生了改变,导致activity关闭并重启,官方的解释如下

Lists configuration changes that the activity will handle itself. When a configuration change occurs at runtime, the activity is shut down and restarted by default, but declaring a configuration with this attribute will prevent the activity from being restarted. Instead, the activity remains running and its onConfigurationChanged() method is called.

大致意思是:

那些被列举的属性configuration改变时activity是否保存自己的状态。当发生配置更改时,默认情况下该activity将关闭并重新启动,但是使用该属性声明配置将阻止该活动重新启动。相反,该activity保持运行,并调用它的onConfigurationChanged()方法。

使用方法如下

<!-- Any or all of the following strings are valid values for this attribute. Multiple values are separated by '|' — for example, "locale|navigation|orientation". -->
<activity
    android:name="....Activity***"
    android:configChanges="locale|navigation|orientation..."
    <intent-filter>
        <category android:name="android.intent.category.HOME" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.MAIN" />
    </intent-filter>
</activity>

属性中包含的值如下

Value

Description

"density"

显示密度已更改-用户可能指定了不同的显示比例,或者现在可能正在激活其他显示。

在API级别24中添加

"fontScale"

字体缩放比例已更改-用户选择了新的全局字体大小。

"keyboard"

键盘类型已更改-例如,用户已插入外部键盘。

"keyboardHidden"

键盘的可访问性已更改-例如,用户显示了硬件键盘。

"layoutDirection"

布局方向已更改-例如,从左到右(LTR)更改为从右到左(RTL)。

在API级别17中添加

"locale"

语言环境已更改-用户选择了一种新的语言来显示文本。

"mcc"

IMSI移动国家/地区代码(MCC)已更改-已检测到SIM卡并更新了MCC。

"mnc"

IMSI移动网络代码(MNC)已更改-已检测到SIM卡并更新了MNC。

"navigation"

导航类型(轨迹球/ dpad)已更改。(这通常不会发生。)

"orientation"

屏幕方向已更改-用户已旋转设备。

注意:如果您的应用程序面向Android 3.2(API级别13)或更高版本,则还应声明 "screenSize""screenLayout"配置,因为当设备在纵向和横向之间切换时,它们也可能会更改。

"screenLayout"

屏幕布局已更改-现在可能正在激活其他显示。

"screenSize"

当前的可用屏幕尺寸已更改。

这表示相对于当前长宽比的当前可用大小的更改,因此当用户在横向和纵向之间切换时,此更改将改变。

在API级别13中添加

"smallestScreenSize"

物理屏幕尺寸已更改。这表示尺寸的变化而与方向无关,因此仅在实际物理屏幕尺寸已更改(例如切换到外部显示器)时才会更改。对此配置的更改对应于minimumWidth配置的更改 。在API级别13中添加。

"touchscreen"

触摸屏已更改。(这通常不会发生。)

"uiMode"

用户界面模式已更改-用户已将设备放置在桌子或汽车停放区中,或者夜间模式已更改。有关不同UI模式的更多信息,请参见 UiModeManager。

在API级别8中添加

配置更改时需要在activity中重写onConfigurationChanged方法(没有对应操作可不重写)  例如:屏幕方向发生改变时

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    int orientation = newConfig.orientation;
    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
        // TODO: 竖屏操作
    }
    else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // TODO: 横屏操作
    }
}