Android 12 启动画面
从 Android 12 开始,在所有应用的冷启动和温启动期间,系统一律会应用 Android 系统的默认启动画面。默认情况下,此系统默认启动画面由应用的启动器图标元素和主题的 windowBackground(如果是单色)构成。
也就是说,只要你的应用运行在Android 12的系统上,都会受到影响,以支付宝为例,截止到2023-01-24日,在Android 13的系统上冷启动时,可以很明显的看到会出现一个闪屏页,页面中间会显示一个启动图标。这个就是受到了系统影响,没有做适配。
Google应该是想让Android有一个统一的启动风格,但是讲道理推出的有点太晚了,国内的App启动页不仅仅是个简单的展示,有的还要显示广告,且风格也各不相同,都有自己的一套启动ui,所以,推出这个splashscreen对国内的app完全是个负担。
但是不适配的话启动的时候看起来有很怪,会出现两个闪屏页,所以,还是要硬着头皮适配一下。
SplashScreen适配
适配方法也很简单,按照官方文档的步骤来即可。
官方建议我们使用AndroidX中的SplashScreen库,该库使用 SplashScreen API,能够向后兼容,官方宣称可在所有 Android 版本上显示外观和风格一致的启动画面。
但是实际使用并非如此,例如动画在Android 12 以下的系统上不生效,如果需要动画,可自己使用其他方式实现,如果只是显示一个图片,那么就不受影响。
以下是适配步骤
将compileSdkVersion更改为31或以上
compileSdkVersion 31
添加依赖
implementation 'androidx.core:core-splashscreen:1.0.0'
准备启动页面要显示的图片或者动画
新增主题
<style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
<!--背景颜色-->
<item name="windowSplashScreenBackground">@color/white</item>
<!--设置动画或图片,注意动画在Android12 以下不生效 很难受...-->
<item name="windowSplashScreenAnimatedIcon">
@drawable/ic_splash
</item>
<!--动画执行时间-->
<!-- <item name="windowSplashScreenAnimationDuration">1000</item>-->
<!--设置闪屏也后启动页面的主题 说白了 就是app本来的主题-->
<item name="postSplashScreenTheme">@style/Theme.XeonYuTheme</item>
</style>
创建启屏页面 SplashActivity
先指定页面的主题
然后就是代码了,代码非常简单,如果你没有其他需求,直接在oncCreate中调用 installSplashScreen()
,然后正常跳转页面即可.
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/*setContentView 可不写*/
// setContentView(R.layout.activity_splash)
/*创建与页面关联的SplashScreen实例*/
installSplashScreen()
/*跳转页面*/
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
然后运行看看
可以看到,启屏页就ok了,非常简单。
在启动屏幕页面显示弹窗
一般情况下,我们需要在用户首次打开app时弹窗让用户同意隐私协议,以及做一些初始化操作之类的。那这种情况下,如要用户点击同意后再进行跳转。
此时,我们可以使用setKeepOnScreenCondition
配合 setOnExitAnimationListener
,示例代码如下
class SplashActivity : AppCompatActivity() {
/**
* 控制是否保持启动页面的变量,值为false时继续往下走
*/
private val keepOnScreenCondition = AtomicBoolean(true)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/*setContentView 可不写*/
// setContentView(R.layout.activity_splash)
/*创建与页面关联的SplashScreen实例*/
installSplashScreen().apply {
/*保持住启动页面的显示*/
setKeepOnScreenCondition {
keepOnScreenCondition.get()
}
/*指定是否Activity要自己处理启动画面动画 实际上就是keepOnScreenCondition的值为false时这个就会回调*/
setOnExitAnimationListener {
/*在这里我们可以弹窗让用户同意隐私政策*/
val alertDialog = AlertDialog.Builder(this@SplashActivity)
.setTitle("隐私协议")
.setMessage("隐私协议内容")
.setPositiveButton(
"同意"
) { dialog, which ->
/*跳转页面*/
val intent = Intent(this@SplashActivity, MainActivity::class.java)
startActivity(intent)
}
.setNegativeButton("拒绝") { dialog, which ->
this@SplashActivity.finish()
}.create();
alertDialog.show();
}
}
MainScope().launch {
Log.i("SplashActivity", "可以做一些初始化逻辑")
delay(500)
keepOnScreenCondition.compareAndSet(true, false)
}
}
}
再来运行看看:
部分设备debug模式下setOnExitAnimationListener不回调的问题
美滋滋的写完代码后,以为没啥问题了,结果换了个Android12的真机运行后发现一直卡在启动页,并没有弹窗或者跳转页面,试了好多次依旧如此。
加了log发现setOnExitAnimationListener中的回调没有执行。明明是按照官方文档写的,怎么会有问题呢?
仔细看了下文档说是要保证在splashscreen退出前setOnExitAnimationListener,这个我代码是肯定没问题的。
后来手动把app杀死,然后点击图标手动启动时又是正常的,给我整懵了,于是查了下资料发现其他人也遇到了这种问题。
https://issuetracker.google.com/issues/197906327
这个问题被google官方人标记为是预期的,不会解决,解释如下:
意思就是:
这个是有意这样的,因为IDE实际上使用Instrumentation来打开应用程序,所以系统将其解释为一个应用程序打开另一个应用程序,而不是用户单击启动器图标。
所以会出现setOnExitAnimationListener不执行的情况,遇到这种情况手动启动就行了,不用太过在意。
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!