ABOUT ME

-

  • Android) 안드로이드 12 Splash Screen 대응하기
    Android 2022. 3. 9. 18:12


    Android 12의 변경 사항 중 하나인 Splash Screen Api를 적용하는 방법을 알아보려 합니다.

     

     

    안드로이드 12 이전의 스플래시 화면 구현 방법은 

     

    • styleswindowBackground 속성을 넣고, 스플래시를 보여줄 화면에 테마로 지정하는 방법
    • 액티비티나 프래그먼트에 딜레이를 주어 직접 스플래시 화면을 보여주는 방법

     

    위 방법들로 충분히 스플래시 화면을 구현할 수 있지만, 좀 더 유연함을 주기 위해 안드로이드 12에서 Splash Screen API가 추가되었습니다.

     

    대표적으로 앱이 hot start에 있을 때도 위의 방법들은 다시 스플래시 화면을 보여줌으로써 대기시간이 길어져 사용자에게 불편함을 초래할 수 있습니다.

     

    앱 시작 시간

    • cold start : 앱이 처음부터 시작. cold start 전에는 앱의 프로세스를 만들지 않음. (기기 부팅, 앱이 처음 시작하는 경우)
    • warm start : 메모리를 제거한 다음 앱을 다시 시작한 경우. (앱을 장시간 사용하지 않아 프로세스가 후순위로 밀려난 후에 앱을 실행한 경우)
    • hot start : 백그라운드에 있는 앱을 포그라운드로 가져옴. 아직 메모리에 있는 상태. (짧은 시간 내에 다시 앱에 돌아오는 경우)

     

    Android 12에서는 Splash Screen이 강제되어 따로 조치를 취하지 않으면 앱 아이콘이 스플래시 화면으로 적용이 되었습니다. 

     

    안드로이드 12에서 따로 액티비티나 프래그먼트에서 스플래시 화면을 구현해 놓았다면, 기본적으로 보여주는 스플래시와 구현한 스플래시가 차례대로 보이게 되어 스플래시 화면이 2번 보이게 됩니다.

     


    Splash Screen API

     

    Build.gradle

    build.gradle
    
    android {
       compileSdkVersion 31
       ...
    }
    dependencies {
       ...
       implementation 'androidx.core:core-splashscreen:1.0.0-beta01'
    }
    • Splash Screen API를 대응하기 위해 아래와 같이 적용해줍니다.

     

    themes.xml

    themes.xml
    
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="Theme.App.Starting" parent="Theme.SplashScreen">
            <item name="android:windowSplashScreenBackground">@color/...</item>
    	<item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
    	<item name="android:windowSplashScreenAnimationDuration">1000</item>
    	<item name=”android:windowSplashScreenIconBackground”>@color/...</item>
    	<item name=”android:windowSplashScreenBrandingImage”>@drawable/...</item>
            <item name="postSplashScreenTheme">@style/Theme</item>
    
    	<!-- 필요시 다크모드 같은 상황 고려. Status bar and Nav bar configs -->
            <item name="android:statusBarColor" tools:targetApi="l">@color/white</item>
            <item name="android:navigationBarColor">@color/white</item>
            <item name="android:windowLightStatusBar">true</item>
        </style>
    </resources>
    • windowSpalshScreenBackground : 배경의 색을 지정
    • windowSplashScreenAnimatedIcon : 화면 중앙에 아이콘 지정
    • windowSplashScreenAnimationDuration : 스플래시 화면의 지속 시간 지정 
    • windowSplashScreenIconBackground : 스플래시 화면 아이콘 뒤의 배경 색 지정
    • windowSplashScreenBrandImage : 스플래시 화면 하단에 표시할 이미지 지정 (권장 안함)
    • postSplashScreenTheme : 스플래시 화면 후에 보일 화면의 테마 지정

     

     

     

    Splash Screen 치수

    • Branded image : 200 * 800dp
    • App icon with an icon background : 240 * 240 dp
    • App icon without an icon background : 288 * 288dp

     

     

     

     

    manifest.xml

    manifest.xml
    
    <application
         android:name=".MyApplication"
         ..
         android:theme="@style/Theme.App.Starting">
         <activity
             android:name=".ui.MainActivity"
             android:exported="false" />
         <activity
             android:name=".SplashActivity"
             android:theme="@style/Theme.App.Starting"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
    
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
     </application>
    • application 혹은 activitytheme에 스플래시 테마 지정

     

     

    스플래시를 보여줄 화면 지정

    • onCreatesuper.onCreate() 이전에 installSplashScreen() 메서드를 추가해줍니다.
    • installSplashScreen은 선택적으로 애니메이션을 지정하거나 더 길게 화면에 유지할 수 있는 객체를 반환합니다.
    • SplashScreen#setKeepOnScreenCondition을 사용하여 스플래시 화면이 다음 화면으로 이동할 때 부드러운 전환이 가능합니다.
    Activity 
    
    class StartActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            installSplashScreen()
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_start)
        }
    }
    
    @JvmStatic
    public fun Activity.installSplashScreen(): SplashScreen {
        val splashScreen = SplashScreen(this)
        splashScreen.install()
        return splashScreen
    }
    
     class StartActivity : Activity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            val splashScreen = installSplashScreen()
            super.onCreate(savedInstanceState)
    
            // Keep the splash screen visible for this Activity
            splashScreen.setKeepOnScreenCondition { true }
            startSomeNextActivity()
            finish()
         }
       ...

     

     

    스플래시 화면을 더 오랫동안 유지

    • 스플래시 화면은 첫 프레임을 그리는 즉시 닫힙니다.
    • ViewTreeObserver.OnPreDrawListener을 활용해 첫 프레임을 그릴 때 사용할 수 있습니다.
    // Create a new event for the activity.
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Set the layout for the content view.
        setContentView(R.layout.main_activity)
    
        // Set up an OnPreDrawListener to the root view.
        val content: View = findViewById(android.R.id.content)
        content.viewTreeObserver.addOnPreDrawListener(
            object : ViewTreeObserver.OnPreDrawListener {
                override fun onPreDraw(): Boolean {
                    // Check if the initial data is ready.
                    return if (viewModel.isReady) {
                        // The content is ready; start drawing.
                        content.viewTreeObserver.removeOnPreDrawListener(this)
                        true
                    } else {
                        // The content is not ready; suspend.
                        false
                    }
                }
            }
        )
    }

     

    스플래시 화면 닫기 애니메이션 설정

    • Activity.getSplashScreen을 사용해 스플래시 화면의 애니메이션을 지정할 수 있습니다.
    • 해당 콜백이 시작되면 스플래시 화면의 애니메이션 벡터 드로어블이 시작됩니다.
    • 애니메이션의 시작 시점을 알기 위해서는 SplashScreenView.getIconAnimationStartMillis를 사용하여 알 수 있습니다.
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    
        // Add a callback that's called when the splash screen is animating to
        // the app content.
        splashScreen.setOnExitAnimationListener { splashScreenView ->
            // Create your custom animation.
            val slideUp = ObjectAnimator.ofFloat(
                splashScreenView,
                View.TRANSLATION_Y,
                0f,
                -splashScreenView.height.toFloat()
            )
            slideUp.interpolator = AnticipateInterpolator()
            slideUp.duration = 200L
    
            // Call SplashScreenView.remove at the end of your custom animation.
            slideUp.doOnEnd { splashScreenView.remove() }
    
            // Run your animation.
            slideUp.start()
        }
    }
    
    // Get the duration of the animated vector drawable.
    val animationDuration = splashScreenView.iconAnimationDurationMillis
    // Get the start time of the animation.
    val animationStart = splashScreenView.iconAnimationDurationMillis
    // Calculate the remaining duration of the animation.
    val remainingDuration = (
            animationDuration - (SystemClock.uptimeMillis() - animationStart)
        ).coerceAtLeast(0L)

     

     

     

    ※ 참고로 실기기에서 구현해보는 것을 추천드립니다. 에뮬레이터로 확인할 시 지정한 스플래시 아이콘이 화면에 보이지 않았습니다. 에뮬레이터에서 직접 앱을 클릭하여 앱에 들어갈 때는 스플래시 아이콘이 화면에 보입니다..

     

     


    Preference

    스플래시 화면

    A Comprehensive Guide to Android 12’s Splash Screen API

     

    반응형

    댓글

Designed by Me.