Android 12 适配指南——SplashScreen

简介: Android 12(API 31)引入了 SplashScreen 相关API,用于开发Android应用的启动页。SplashScreen相关API的引入影响在Andorid 12设备上运行的所有应用。若开发者未进行SplashScreen的适配工作,在应用冷启动和温启动时,可能会呈现两个启动页先后出现的情况(Android SplashScreen启动页 + Android应用自定义开发的启动页或引导页)。

Android 12(API 31)引入了 SplashScreen 相关API,用于开发Android应用的启动页。

  • 影响在Andorid 12设备上运行的所有应用:

SplashScreen相关API的引入影响在Andorid 12设备上运行的所有应用。这一点对于应用开发者来说,无论你的应用targetSdkVersion 版本是多少,均需要进行SplashScreen的适配工作。

  • 必须进行SplashScreen的适配工作:

若开发者未进行SplashScreen的适配工作,当应用运行于Android 12及以上版本的设备,在应用的冷启动 或 温启动时,Android系统都会构造一个默认启动动画(默认启动动画由应用ICON + 应用主题的windowBackground内容构成)。
因此,对于未进行SplashScreen API适配工作的应用,在冷启动和温启动时,可能会呈现两个启动页先后出现的情况(Android SplashScreen启动页 + Android应用自定义开发的启动页或引导页)。

先看一下Andorid官方给出的SplashScreen启动页运行效果。
SplashScreen启动页运行效果

  • SplashScreen 使用方式
  • SplashScreen 启动页构成
  • SplashScreen 使用举例源码下载

一、使用方式

按照官方相关迁移文档,我开发了以下启动页的运行效果。
SplashScreen_demo

下面以我开发的这个案例效果为例,举例说明SplashScreen相关API的使用方式:

  • build.gradle 添加相关依赖;
  • 自定义SplashScreen主题;
  • 自定义启动页Activity;

1.1 build.gradle

build.gradle 中:

  • 更改 compileSdkVersion 的版本;
  • 引入 splashscreen 相关依赖 ;
android {  
 // 更改 compileSdkVersion 的版本
 compileSdk 31  
}  
  
dependencies {  
 // 引入 splashscreen 相关依赖  
 implementation "androidx.core:core-splashscreen:1.0.0-alpha02"  
}

1.2 SplashScreen主题

创建一个父级为 Theme.SplashScreen 的主题,并将 对应的主题设置到启动页 Activity 应用。

  • 创建自定义的 SplashScreen 主题;
  • SplashScreen 主题应用到对应的Activity;

创建 SplashScreen 主题:

直接给出style的代码举例,主题中各属性均给出了明确的注释说明,不再进行重复说明。
这里特别强调一下,windowSplashScreenAnimatedIcon 这个属性,可以是一个 图片、帧动画、animated-vector动画 等。

<!-- Splash启动页Style -->
<style name="Theme.SplashScreen.Demo" parent="Theme.SplashScreen">
    <!--启动画面背景颜色-->
    <item name="windowSplashScreenBackground">@color/splashscreen_bg</item>
    <!-- 启动画面icon图标:这里可以是图片、帧动画等-->
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_anim_icon</item>
    <item name="windowSplashScreenIconBackgroundColor">@color/splashscreen_icon_bg</item>
    <!-- icon动画在关闭之前显示的时长:最长时间为1000毫秒-->
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <!-- 启动画面底部的 Brand 图片-->
    <item name="android:windowSplashScreenBrandingImage">@drawable/brand_img</item>
    <!-- Splash退出后的主题-->
    <item name="postSplashScreenTheme">@style/Theme.Android12_Splash</item>
</style>

SplashScreen 主题应用到启动页Activity

这个启动页我自定义为 SplashActivity

<activity
    android:name=".SplashActivity"
    android:exported="true"
    android:theme="@style/Theme.SplashScreen.Demo">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

1.3 启动页Activity

上文提到,这个启动页的Activity,我自定定义为 SplashActivity,源码如下:

class SplashActivity : AppCompatActivity() {
    val TAG: String = "CoroutineScope"

    // 协程( 了解协程的使用,可参考:https://xiaxl.blog.csdn.net/article/details/123383727 )
    lateinit var mCoroutineScope: CoroutineScope

    // 数据
    private var mKeepOnAtomicBool = AtomicBoolean(true)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "----onCreate----")

        // 初始化操作(必须放在setContentView()之前)
        val mSplashScreen = installSplashScreen()
        // setContentView(可以省略)
        setContentView(R.layout.activity_splash)

        // 每次UI绘制前,会判断 Splash 是否有必要继续展示在屏幕上;直到不再满足条件时,隐藏Splash。
        mSplashScreen!!.setKeepVisibleCondition(object : SplashScreen.KeepOnScreenCondition {
            override fun shouldKeepOnScreen(): Boolean {
                return mKeepOnAtomicBool.get()
            }
        })

        // Splash展示完毕的监听方法
        mSplashScreen!!.setOnExitAnimationListener(object : SplashScreen.OnExitAnimationListener {
            override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
                startSplashScreenExit(splashScreenViewProvider)
            }
        })

        // 创建 CoroutineScope (用于管理CoroutineScope中的所有协程)
        mCoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
        mCoroutineScope.launch(Dispatchers.IO) {
            Log.d(TAG, "----launch----")
            // TODO 异步线程
            // Splash展示2秒钟
            delay(2000)
            // Splash 展示完毕
            mKeepOnAtomicBool.compareAndSet(true, false)
        }
    }

    /**
     * onDestroy
     */
    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "----onDestroy----")
        // 当 Activity 销毁的时候取消该 Scope 管理的所有协程。
        mCoroutineScope.cancel()
    }

    /**
     * SplashScreen 退出时执行
     */
    private fun startSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
        Log.d(TAG, "----onSplashScreenExit----")
        // splashScreenView
        val splashScreenView = splashScreenViewProvider.view
        // splashIconView
        val iconView = splashScreenViewProvider.iconView

        /**
         * ScreenView alpha 动画
         */
        val splashAlphaAnim = ObjectAnimator.ofFloat(splashScreenView, View.ALPHA, 1f, 0f)
        splashAlphaAnim.duration = 500
        splashAlphaAnim.interpolator = FastOutLinearInInterpolator()

        /**
         * iconView 向下移动的动画
         */
        val translationY = ObjectAnimator.ofFloat(
            iconView,
            View.TRANSLATION_Y,
            iconView.translationY,
            splashScreenView.height.toFloat()
        )
        translationY.duration = 500
        translationY.interpolator = FastOutLinearInInterpolator()

        // 合并渐变动画 & 下移动画
        val animatorSet = AnimatorSet()
        animatorSet.playTogether(translationY, splashAlphaAnim)
        // 动画结束时调用的方法
        animatorSet.doOnEnd { onAnimEnd(splashScreenViewProvider) }
        // 开启动画
        animatorSet.start()
    }

    /**
     * 当动画结束
     */
    private fun onAnimEnd(splashScreenViewProvider: SplashScreenViewProvider) {
        //移除监听
        splashScreenViewProvider.remove()
        //跳转下个页面
        // 进入主界面
        Log.d(TAG, "----startActivity MainActivity----")
        startActivity(Intent(this@SplashActivity, MainActivity::class.java))
        this@SplashActivity.finish()
        Log.d(TAG, "----SplashActivity finish----")
        // Activity 退场动画
        overridePendingTransition(0, R.anim.activity_out)
    }
}

二、SplashScreen构成

仍然以本案例的代码效果进行举例说明。

  • SplashScreen 构成
  • SplashScreen 中心ICON的大小

SplashScreen 构成

前边介绍SplashScreen主题代码时,提到过我自定的Theme.SplashScreen.Demo主题:

<!-- Splash启动页Style -->
<style name="Theme.SplashScreen.Demo" parent="Theme.SplashScreen">
    <!--启动画面背景颜色-->
    <item name="windowSplashScreenBackground">@color/splashscreen_bg</item>
    <!-- 启动画面icon图标:这里可以是图片、帧动画等-->
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_anim_icon</item>
    <item name="windowSplashScreenIconBackgroundColor">@color/splashscreen_icon_bg</item>
    <!-- icon动画在关闭之前显示的时长:最长时间为1000毫秒-->
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <!-- 启动画面底部的 Brand 图片-->
    <item name="android:windowSplashScreenBrandingImage">@drawable/brand_img</item>
    <!-- Splash退出后的主题-->
    <item name="postSplashScreenTheme">@style/Theme.Android12_Splash</item>
</style>

其对应的属性位置如下图所示:

SplashScreen 构成

SplashScreen 中心ICON大小

关于 SplashScreen 中心ICON的dp大小,我们需查看Android X的对应源码:

SplashScreen 中心ICON大小

三、案例源码

本案例中SplashScreen案例源代码下载地址如下:
https://download.csdn.net/download/aiwusheng/84992053

参考

Android将启动画面迁移到SplashScreen:
https://developer.android.google.cn/guide/topics/ui/splash-screen/migrate

Android12 SplashScreen:
https://developer.android.google.cn/about/versions/12/features/splash-screen

= THE END =

文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。
文章首发于公众号”CODING技术小馆“,如果文章对您有帮助,欢迎关注我的公众号。

目录
相关文章
|
6月前
|
Web App开发 移动开发 小程序
"项目中mpaas升级到10.2.3 适配Android 14之后 app中的H5以及小程序都访问不了,
"项目中mpaas升级到10.2.3 适配Android 14之后 app中的H5以及小程序都访问不了,显示“网络不给力,请稍后再试”,预发内网版本不能使用,线上版本可以正常使用,这个是什么原因啊,是某些参数没有配置吗,还是说是一些参数改错了?
108 2
|
Android开发
Android 全屏适配刘海机型
Android 全屏适配刘海机型
183 0
|
2月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
199 6
|
4月前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
3月前
|
安全 Java Android开发
Android 14适配Google play截止时间临近,适配注意点和经验
本文介绍了Android 14带来的关键更新,包括性能优化、定制化体验、多语言支持、多媒体与图形增强等功能。此外,还强调了适配时的重要事项,如targetSdkVersion升级、前台服务类型声明、蓝牙权限变更等,以及安全性与用户体验方面的改进。开发者需按官方指南更新应用,以充分利用新特性并确保兼容性和安全性。
272 0
|
6月前
|
编解码 人工智能 测试技术
安卓适配性策略:确保应用在不同设备上的兼容性
【4月更文挑战第13天】本文探讨了提升安卓应用兼容性的策略,包括理解平台碎片化、设计响应式UI(使用dp单位,考虑横竖屏)、利用Android SDK的兼容工具(支持库、资源限定符)、编写兼容性代码(运行时权限、设备特性检查)以及优化性能以适应低端设备。适配性是安卓开发的关键,通过这些方法可确保应用在多样化设备上提供一致体验。未来,自动化测试和AI将助力应对设备碎片化挑战。
686 4
|
存储 5G API
Android 11 来袭,一起来看看怎么适配(三)
Android 11 来袭,一起来看看怎么适配
|
安全 Shell 测试技术
Android 11 来袭,一起来看看怎么适配(二)
Android 11 来袭,一起来看看怎么适配
|
安全 API 开发工具
Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(下)
Android14 适配之——targetSdkVersion 升级到 34 需要注意些什么?(下)
1310 0
|
存储 缓存 安全
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?
518 0
下一篇
无影云桌面