From fa0b54bb9e262a88781a9a7580ec4196cd528a4a Mon Sep 17 00:00:00 2001
From: Camille Simon <43054281+camsim99@users.noreply.github.com>
Date: Mon, 18 Oct 2021 14:45:11 -0700
Subject: [PATCH] Add android_splash_screen (#903)
Adds a Flutter app designed for devices running at least Android 12 that exemplifies how to implement an animated splash screen with the SplashScreen API.
---
android_splash_screen/.gitignore | 71 ++++++
android_splash_screen/.metadata | 10 +
android_splash_screen/README.md | 35 +++
android_splash_screen/analysis_options.yaml | 19 ++
android_splash_screen/android/.gitignore | 11 +
.../android/app/build.gradle | 71 ++++++
.../android/app/src/debug/AndroidManifest.xml | 7 +
.../android/app/src/main/AndroidManifest.xml | 41 ++++
.../splash_screen_sample/MainActivity.kt | 211 ++++++++++++++++++
.../app/src/main/res/drawable/android.xml | 24 ++
.../main/res/drawable/android_background.xml | 22 ++
.../main/res/drawable/splashscreen_icon.xml | 80 +++++++
.../app/src/main/res/layout/main_activity.xml | 58 +++++
.../src/main/res/layout/main_activity_2.xml | 76 +++++++
.../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes
.../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes
.../app/src/main/res/values-night/styles.xml | 33 +++
.../android/app/src/main/res/values/color.xml | 21 ++
.../app/src/main/res/values/dimens.xml | 17 ++
.../app/src/main/res/values/styles.xml | 33 +++
.../app/src/profile/AndroidManifest.xml | 7 +
android_splash_screen/android/build.gradle | 29 +++
.../android/gradle.properties | 3 +
.../gradle/wrapper/gradle-wrapper.properties | 6 +
android_splash_screen/android/settings.gradle | 11 +
android_splash_screen/images/androidIcon.png | Bin 0 -> 33569 bytes
android_splash_screen/lib/main.dart | 115 ++++++++++
android_splash_screen/pubspec.yaml | 23 ++
android_splash_screen/test/widget_test.dart | 9 +
tool/flutter_ci_script_beta.sh | 1 +
tool/flutter_ci_script_dev.sh | 1 +
tool/flutter_ci_script_stable.sh | 1 +
35 files changed, 1046 insertions(+)
create mode 100644 android_splash_screen/.gitignore
create mode 100644 android_splash_screen/.metadata
create mode 100644 android_splash_screen/README.md
create mode 100644 android_splash_screen/analysis_options.yaml
create mode 100644 android_splash_screen/android/.gitignore
create mode 100644 android_splash_screen/android/app/build.gradle
create mode 100644 android_splash_screen/android/app/src/debug/AndroidManifest.xml
create mode 100644 android_splash_screen/android/app/src/main/AndroidManifest.xml
create mode 100644 android_splash_screen/android/app/src/main/kotlin/com/example/splash_screen_sample/MainActivity.kt
create mode 100644 android_splash_screen/android/app/src/main/res/drawable/android.xml
create mode 100644 android_splash_screen/android/app/src/main/res/drawable/android_background.xml
create mode 100644 android_splash_screen/android/app/src/main/res/drawable/splashscreen_icon.xml
create mode 100644 android_splash_screen/android/app/src/main/res/layout/main_activity.xml
create mode 100644 android_splash_screen/android/app/src/main/res/layout/main_activity_2.xml
create mode 100644 android_splash_screen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
create mode 100644 android_splash_screen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
create mode 100644 android_splash_screen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
create mode 100644 android_splash_screen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
create mode 100644 android_splash_screen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
create mode 100644 android_splash_screen/android/app/src/main/res/values-night/styles.xml
create mode 100644 android_splash_screen/android/app/src/main/res/values/color.xml
create mode 100644 android_splash_screen/android/app/src/main/res/values/dimens.xml
create mode 100644 android_splash_screen/android/app/src/main/res/values/styles.xml
create mode 100644 android_splash_screen/android/app/src/profile/AndroidManifest.xml
create mode 100644 android_splash_screen/android/build.gradle
create mode 100644 android_splash_screen/android/gradle.properties
create mode 100644 android_splash_screen/android/gradle/wrapper/gradle-wrapper.properties
create mode 100644 android_splash_screen/android/settings.gradle
create mode 100644 android_splash_screen/images/androidIcon.png
create mode 100644 android_splash_screen/lib/main.dart
create mode 100644 android_splash_screen/pubspec.yaml
create mode 100644 android_splash_screen/test/widget_test.dart
diff --git a/android_splash_screen/.gitignore b/android_splash_screen/.gitignore
new file mode 100644
index 000000000..fa1413672
--- /dev/null
+++ b/android_splash_screen/.gitignore
@@ -0,0 +1,71 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+local.properties
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.gradle
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
+
+# See https://www.dartlang.org/guides/libraries/private-files
+
+# Files and directories created by pub
+.dart_tool/
+.packages
+build/
+# If you're building an application, you may want to check-in your pubspec.lock
+pubspec.lock
+
+# Directory created by dartdoc
+# If you don't generate documentation locally you can remove this line.
+doc/api/
+
+# Avoid committing generated Javascript files:
+*.dart.js
+*.info.json # Produced by the --dump-info flag.
+*.js # When generated by dart2js. Don't specify *.js if your
+ # project includes source files written in JavaScript.
+*.js_
+*.js.deps
+*.js.map
+
diff --git a/android_splash_screen/.metadata b/android_splash_screen/.metadata
new file mode 100644
index 000000000..56bfc2c4d
--- /dev/null
+++ b/android_splash_screen/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: f4abaa0735eba4dfd8f33f73363911d63931fe03
+ channel: stable
+
+project_type: app
diff --git a/android_splash_screen/README.md b/android_splash_screen/README.md
new file mode 100644
index 000000000..54c46db31
--- /dev/null
+++ b/android_splash_screen/README.md
@@ -0,0 +1,35 @@
+# Splash Screen Sample
+
+A Flutter app that exemplifies how to implement an animated splash screen for Android devices running at least Android 12, the version that supplies the new [SplashScreen API](https://developer.android.com/about/versions/12/features/splash-screen).
+
+**NOTE:** There is a pub package available to implement static splash screens in your Flutter app: [flutter_native_splash](https://pub.dev/packages/flutter_native_splash).
+
+## Goals
+- Demonstrate the compatibility of animated splash screens and Flutter apps running on Android
+- Demonstrate the smoothness achievable by a splash screen as a transition to the Flutter UI
+
+## The important bits
+
+### Remove deprecated code
+
+When creating a Flutter app, the Android code generated may include the deprecated implementation of a splash screen. This includes a definition of `io.flutter.embedding.android.SplashScreenDrawable` in the ` /android/app/src/main/AndroidManifest.xml` file and an implementation of `provideSplashScreen()` in the `/android/app/src/main/kotlin/MainActivity.kt` file. Make sure to remove this code.
+
+**NOTE:** This should no longer be a concern as of Flutter 2.5.
+
+### Modify Android build files
+In order to support the Android 12 SplashScreen API, you need to:
+1. Update the Android `compileSdkVersion` to 31 in the `/android/app/build.gradle` file, and
+2. Update the `ext.kotlin_version` to the latest Kotlin extension version (1.5.31 at the time of publication) in the `/android/build.gradle` file.
+
+### Timing the splash screen animation
+In order to ensure a smooth transition between the animated splash screen and the Flutter UI displaying for the first time, be sure to handle both the case where the Flutter UI is ready to be displayed before the animation finishes and vice versa. This can be done by overriding `onFlutterUiDisplayed()` and `onFlutterUiNoLongerDisplayed()` in `/android/app/src/main/kotlin/com/example/splash-screen-sample/MainActivity.kt`, the implementation of `FlutterActivity` in this project.
+
+## Questions/Issues
+
+If you have a general question about splash screens or their implementation in Flutter, the best places to go are:
+
+* [Android 12 Splash Screen Documentation](https://developer.android.com/about/versions/12/features/splash-screen)
+* [Flutter Guidance on Adding a Splash Screen to Your App](https://flutter.dev/docs/development/ui/advanced/splash-screen?tab=android-splash-alignment-kotlin-tab)
+
+If you run into an issue with the sample itself, please file an issue
+in the [main Flutter repo](https://github.com/flutter/flutter/issues).
diff --git a/android_splash_screen/analysis_options.yaml b/android_splash_screen/analysis_options.yaml
new file mode 100644
index 000000000..85f6fbe91
--- /dev/null
+++ b/android_splash_screen/analysis_options.yaml
@@ -0,0 +1,19 @@
+include: package:flutter_lints/flutter.yaml
+
+analyzer:
+ strong-mode:
+ implicit-casts: false
+ implicit-dynamic: false
+
+linter:
+ rules:
+ avoid_types_on_closure_parameters: true
+ avoid_void_async: true
+ cancel_subscriptions: true
+ close_sinks: true
+ directives_ordering: true
+ package_api_docs: true
+ package_prefixed_library_names: true
+ test_types_in_equals: true
+ throw_in_finally: true
+ unnecessary_statements: true
diff --git a/android_splash_screen/android/.gitignore b/android_splash_screen/android/.gitignore
new file mode 100644
index 000000000..0a741cb43
--- /dev/null
+++ b/android_splash_screen/android/.gitignore
@@ -0,0 +1,11 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
diff --git a/android_splash_screen/android/app/build.gradle b/android_splash_screen/android/app/build.gradle
new file mode 100644
index 000000000..8c01625b4
--- /dev/null
+++ b/android_splash_screen/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 31
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.splash_screen_sample"
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "androidx.core:core-splashscreen:1.0.0-alpha02"
+ implementation "androidx.core:core:1.5.0-alpha05"
+ implementation "androidx.core:core-ktx:1.6.0"
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
+ implementation "androidx.core:core-animation:1.0.0-alpha02"
+ implementation "androidx.interpolator:interpolator:1.0.0"
+ def appcompat_version = "1.3.1"
+
+ implementation "androidx.appcompat:appcompat:$appcompat_version"
+ // For loading and tinting drawables on older versions of the platform
+ implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
+ implementation "androidx.constraintlayout:constraintlayout:2.1.0"
+}
diff --git a/android_splash_screen/android/app/src/debug/AndroidManifest.xml b/android_splash_screen/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 000000000..0dea87e8b
--- /dev/null
+++ b/android_splash_screen/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android_splash_screen/android/app/src/main/AndroidManifest.xml b/android_splash_screen/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..ad41ca2a4
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android_splash_screen/android/app/src/main/kotlin/com/example/splash_screen_sample/MainActivity.kt b/android_splash_screen/android/app/src/main/kotlin/com/example/splash_screen_sample/MainActivity.kt
new file mode 100644
index 000000000..d3efc96d7
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/kotlin/com/example/splash_screen_sample/MainActivity.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.splash_screen_sample
+
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
+import android.os.Bundle
+import android.transition.AutoTransition
+import android.transition.Transition
+import android.transition.TransitionManager
+import android.view.animation.AccelerateDecelerateInterpolator
+import android.view.View
+import android.widget.FrameLayout
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.core.animation.doOnEnd
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.core.splashscreen.SplashScreenViewProvider
+import androidx.core.view.postDelayed
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.interpolator.view.animation.FastOutLinearInInterpolator
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity : FlutterActivity() {
+
+ var flutterUIReady : Boolean = false
+ var initialAnimationFinished : Boolean = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // This activity will be handling the splash screen transition.
+ val splashScreen = installSplashScreen()
+
+ // The splash screen goes edge to edge, so for a smooth transition to our app, also
+ // want to draw edge to edge.
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+ val insetsController = WindowCompat.getInsetsController(window, window.decorView)
+ insetsController?.isAppearanceLightNavigationBars = true
+ insetsController?.isAppearanceLightStatusBars = true
+
+ // The content view needs to be set before calling setOnExitAnimationListener
+ // to ensure that the SplashScreenView is attached to the right view root.
+ val rootLayout = findViewById(android.R.id.content) as FrameLayout
+ View.inflate(this, R.layout.main_activity_2, rootLayout)
+
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.container)) { view, windowInsets ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+ view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
+ windowInsets.inset(insets)
+ }
+
+ // Setting an OnExitAnimationListener on the splash screen indicates
+ // to the system that the application will handle the exit animation.
+ // The listener will be called once the app is ready.
+ splashScreen.setOnExitAnimationListener { splashScreenViewProvider ->
+ onSplashScreenExit(splashScreenViewProvider)
+ }
+ }
+
+ override fun onFlutterUiDisplayed(){
+ flutterUIReady = true
+
+ if (initialAnimationFinished) {
+ hideSplashScreenAnimation()
+ }
+ }
+
+ override fun onFlutterUiNoLongerDisplayed(){
+ flutterUIReady = false
+ }
+
+ /**
+ * Hides the splash screen only when the entire animation has finished and the Flutter UI is ready to display.
+ */
+ private fun hideSplashScreenAnimation(){
+ val splashView = findViewById(R.id.container) as ConstraintLayout
+ splashView
+ .animate()
+ .alpha(0.0f)
+ .setDuration(SPLASHSCREEN_FINAL_ANIMATION_ALPHA_ANIMATION_DURATION)
+ }
+
+ /**
+ * Handles the transition from the splash screen to the application.
+ */
+ private fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
+ val accelerateInterpolator = FastOutLinearInInterpolator()
+ val splashScreenView = splashScreenViewProvider.view
+ val iconView = splashScreenViewProvider.iconView
+
+ // Change the alpha of the main view.
+ val alpha = ValueAnimator.ofInt(255, 0)
+ alpha.duration = SPLASHSCREEN_ALPHA_ANIMATION_DURATION
+ alpha.interpolator = accelerateInterpolator
+
+ // And translate the icon down.
+ val translationY = ObjectAnimator.ofFloat(
+ iconView,
+ View.TRANSLATION_Y,
+ iconView.translationY,
+ splashScreenView.height.toFloat()
+ )
+ translationY.duration = SPLASHSCREEN_TY_ANIMATION_DURATION
+ translationY.interpolator = accelerateInterpolator
+
+ // And play all of the animation together.
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(alpha)
+
+ // Apply layout constraints of starting frame of animation to
+ // FrameLayout's container for the TransitionManager to know
+ // where to start the transition.
+ val root = findViewById(R.id.container)
+ val set1 = ConstraintSet().apply {
+ clone(this@MainActivity, R.layout.main_activity)
+ }
+ set1.applyTo(root)
+
+ // Retrieve layout constraints of final frame of animation
+ // for TransitionManager to know where to end the transition.
+ val set2 = ConstraintSet().apply {
+ clone(this@MainActivity, R.layout.main_activity_2)
+ }
+
+ var transitionStarted = false
+ val autoTransition = AutoTransition().apply {
+ interpolator = AccelerateDecelerateInterpolator()
+ }
+ autoTransition.addListener(object: Transition.TransitionListener {
+ override fun onTransitionEnd(transition: Transition) {
+ initialAnimationFinished = true
+
+ if (flutterUIReady) {
+ hideSplashScreenAnimation()
+ }
+ }
+ override fun onTransitionCancel(transition: Transition){}
+ override fun onTransitionPause(transition: Transition) {}
+ override fun onTransitionResume(transition: Transition) {}
+ override fun onTransitionStart(transition: Transition) {}
+ })
+
+ val alphaUpdateListener: (ValueAnimator) -> Unit = { valueAnimator ->
+ if (!transitionStarted && valueAnimator.animatedFraction > 0.5) {
+ transitionStarted = true
+
+ TransitionManager.beginDelayedTransition(root, autoTransition)
+ iconView.visibility = View.GONE
+
+ // Apply constraints of final frame of animation to
+ // FrameLayout's container once the transition is in progress.
+ set2.applyTo(root)
+ }
+ splashScreenView.background.alpha = valueAnimator.animatedValue as Int
+ }
+ alpha.addUpdateListener(alphaUpdateListener)
+
+ // Once the application is finished, remove the splash screen from our view
+ // hierarchy.
+ animatorSet.doOnEnd {
+ splashScreenViewProvider.remove()
+ }
+
+ waitForAnimatedIconToFinish(splashScreenViewProvider, splashScreenView) {
+ animatorSet.start()
+ }
+ }
+
+ /**
+ * Wait until the AVD animation is finished before starting the splash screen dismiss animation.
+ */
+ private fun SplashScreenViewProvider.remainingAnimationDuration() = iconAnimationStartMillis +
+ iconAnimationDurationMillis - System.currentTimeMillis()
+
+ private fun waitForAnimatedIconToFinish(
+ splashScreenViewProvider: SplashScreenViewProvider,
+ view: View,
+ onAnimationFinished: () -> Unit
+ ) {
+ // If wanting to wait for our Animated Vector Drawable to finish animating, can compute
+ // the remaining time to delay the start of the exit animation.
+ val delayMillis: Long =
+ if (WAIT_FOR_AVD_TO_FINISH) splashScreenViewProvider.remainingAnimationDuration() else 0
+ view.postDelayed(delayMillis, onAnimationFinished)
+ }
+
+ private companion object {
+ const val SPLASHSCREEN_ALPHA_ANIMATION_DURATION = 500 as Long
+ const val SPLASHSCREEN_TY_ANIMATION_DURATION = 500 as Long
+ const val SPLASHSCREEN_FINAL_ANIMATION_ALPHA_ANIMATION_DURATION = 250 as Long
+ const val WAIT_FOR_AVD_TO_FINISH = false
+ }
+}
diff --git a/android_splash_screen/android/app/src/main/res/drawable/android.xml b/android_splash_screen/android/app/src/main/res/drawable/android.xml
new file mode 100644
index 000000000..cf1152ba6
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/drawable/android.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_splash_screen/android/app/src/main/res/drawable/android_background.xml b/android_splash_screen/android/app/src/main/res/drawable/android_background.xml
new file mode 100644
index 000000000..091aab817
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/drawable/android_background.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_splash_screen/android/app/src/main/res/drawable/splashscreen_icon.xml b/android_splash_screen/android/app/src/main/res/drawable/splashscreen_icon.xml
new file mode 100644
index 000000000..d7185482f
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/drawable/splashscreen_icon.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android_splash_screen/android/app/src/main/res/layout/main_activity.xml b/android_splash_screen/android/app/src/main/res/layout/main_activity.xml
new file mode 100644
index 000000000..5e0f370c7
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/layout/main_activity.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/android_splash_screen/android/app/src/main/res/layout/main_activity_2.xml b/android_splash_screen/android/app/src/main/res/layout/main_activity_2.xml
new file mode 100644
index 000000000..474a52084
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/layout/main_activity_2.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android_splash_screen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android_splash_screen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29
GIT binary patch
literal 544
zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G}
zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc
zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs
zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG
zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0
zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~
AQ2+n{
literal 0
HcmV?d00001
diff --git a/android_splash_screen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android_splash_screen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be
GIT binary patch
literal 442
zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB
zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q0|W-^A&VhjhO+044$%!YxiPI;`p4Q#=k
za-F;6dk-j1J*_nBlG2>3KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l
zytQ?X=U+MF$@3
zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+
yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs
z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM
zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R`
zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM
zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg
zoq1^2_p9@|WEo
z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q&
zrYBH{QP^@Sti!`2)uG{irBBq@y*$B
zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N
zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$
literal 0
HcmV?d00001
diff --git a/android_splash_screen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android_splash_screen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c
GIT binary patch
literal 1031
zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_%
zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3
zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc
z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R
zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2
z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b
zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE
z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o
zo~|9I;xof
literal 0
HcmV?d00001
diff --git a/android_splash_screen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android_splash_screen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0
GIT binary patch
literal 1443
zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY
zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv
za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw
zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3
z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w!
zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u
zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad
z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt*
zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW
zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w
z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf<
zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$
zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v
zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq
z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek
zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+
zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q
zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl
z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f
z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H
zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP
z(1P?z~7YxD~Rf<(a@_y`
literal 0
HcmV?d00001
diff --git a/android_splash_screen/android/app/src/main/res/values-night/styles.xml b/android_splash_screen/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 000000000..31895e302
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
diff --git a/android_splash_screen/android/app/src/main/res/values/color.xml b/android_splash_screen/android/app/src/main/res/values/color.xml
new file mode 100644
index 000000000..21b791d2f
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/values/color.xml
@@ -0,0 +1,21 @@
+
+
+
+ #034565
+ #034565
+ #FFFFFF
+
diff --git a/android_splash_screen/android/app/src/main/res/values/dimens.xml b/android_splash_screen/android/app/src/main/res/values/dimens.xml
new file mode 100644
index 000000000..f76be91ae
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/values/dimens.xml
@@ -0,0 +1,17 @@
+
+
+
+ 30dp
+ 10dp
+
diff --git a/android_splash_screen/android/app/src/main/res/values/styles.xml b/android_splash_screen/android/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000..994813030
--- /dev/null
+++ b/android_splash_screen/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
diff --git a/android_splash_screen/android/app/src/profile/AndroidManifest.xml b/android_splash_screen/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 000000000..0dea87e8b
--- /dev/null
+++ b/android_splash_screen/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android_splash_screen/android/build.gradle b/android_splash_screen/android/build.gradle
new file mode 100644
index 000000000..d084b6f47
--- /dev/null
+++ b/android_splash_screen/android/build.gradle
@@ -0,0 +1,29 @@
+buildscript {
+ ext.kotlin_version = '1.5.31'
+ repositories {
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/android_splash_screen/android/gradle.properties b/android_splash_screen/android/gradle.properties
new file mode 100644
index 000000000..94adc3a3f
--- /dev/null
+++ b/android_splash_screen/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/android_splash_screen/android/gradle/wrapper/gradle-wrapper.properties b/android_splash_screen/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..bc6a58afd
--- /dev/null
+++ b/android_splash_screen/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
diff --git a/android_splash_screen/android/settings.gradle b/android_splash_screen/android/settings.gradle
new file mode 100644
index 000000000..44e62bcf0
--- /dev/null
+++ b/android_splash_screen/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/android_splash_screen/images/androidIcon.png b/android_splash_screen/images/androidIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..72e87ff7f1525004a6ca140e8c5f2c30b1075f56
GIT binary patch
literal 33569
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 main() async {
+ runApp(const MyApp());
+}
+
+/* Main widget that contains the Flutter starter app. */
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({Key? key, required this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ int _counter = 0;
+
+ void _incrementCounter() {
+ setState(() {
+ _counter++;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Center(
+ child: Column(
+ children: [
+ const Padding(
+ padding: EdgeInsets.only(top: 42, bottom: 250),
+ child: Align(
+ alignment: Alignment.topCenter, child: CustomAppBar())),
+ const Text(
+ 'You have pushed the button this many times:',
+ ),
+ Text(
+ '$_counter',
+ style: Theme.of(context).textTheme.headline4,
+ ),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: _incrementCounter,
+ tooltip: 'Increment',
+ child: const Icon(Icons.add),
+ ),
+ );
+ }
+}
+
+/* A Flutter implementation of the last frame of the splashscreen animation */
+class CustomAppBar extends StatelessWidget {
+ const CustomAppBar({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ Widget titleSection = Row(
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(left: 12, right: 4),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(36.0),
+ child: Image.asset(
+ 'images/androidIcon.png',
+ width: 72.0,
+ height: 72.0,
+ fit: BoxFit.fill,
+ ),
+ ),
+ ),
+ const Padding(
+ padding: EdgeInsets.only(top: 3),
+ child: Text("Super Splash Screen Demo",
+ style: TextStyle(color: Colors.black54, fontSize: 24)),
+ ),
+ ],
+ );
+ return titleSection;
+ }
+}
diff --git a/android_splash_screen/pubspec.yaml b/android_splash_screen/pubspec.yaml
new file mode 100644
index 000000000..4b53126cc
--- /dev/null
+++ b/android_splash_screen/pubspec.yaml
@@ -0,0 +1,23 @@
+name: splash_screen_sample
+description: A sample Flutter app with animated splash screen on Android 12.
+
+publish_to: 'none'
+
+version: 1.0.0+1
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^1.0.4
+
+flutter:
+ uses-material-design: true
+ assets:
+ - images/androidIcon.png
diff --git a/android_splash_screen/test/widget_test.dart b/android_splash_screen/test/widget_test.dart
new file mode 100644
index 000000000..99fe91029
--- /dev/null
+++ b/android_splash_screen/test/widget_test.dart
@@ -0,0 +1,9 @@
+// Copyright 2020 The Flutter team. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('This test always passes', (tester) async {});
+}
diff --git a/tool/flutter_ci_script_beta.sh b/tool/flutter_ci_script_beta.sh
index 1730f07ef..96e1df85f 100755
--- a/tool/flutter_ci_script_beta.sh
+++ b/tool/flutter_ci_script_beta.sh
@@ -13,6 +13,7 @@ declare -ar PROJECT_NAMES=(
"add_to_app/multiple_flutters/multiple_flutters_module"
"add_to_app/plugin/flutter_module_using_plugin"
"add_to_app/prebuilt_module/flutter_module"
+ "android_splash_screen"
"animations"
"experimental/desktop_photo_search"
"experimental/federated_plugin/federated_plugin"
diff --git a/tool/flutter_ci_script_dev.sh b/tool/flutter_ci_script_dev.sh
index 7fae8e217..8e010e113 100755
--- a/tool/flutter_ci_script_dev.sh
+++ b/tool/flutter_ci_script_dev.sh
@@ -13,6 +13,7 @@ declare -ar PROJECT_NAMES=(
"add_to_app/multiple_flutters/multiple_flutters_module"
"add_to_app/plugin/flutter_module_using_plugin"
"add_to_app/prebuilt_module/flutter_module"
+ "android_splash_screen"
"animations"
"experimental/desktop_photo_search"
"experimental/federated_plugin/federated_plugin"
diff --git a/tool/flutter_ci_script_stable.sh b/tool/flutter_ci_script_stable.sh
index 2733b2b5f..cf2801ec8 100755
--- a/tool/flutter_ci_script_stable.sh
+++ b/tool/flutter_ci_script_stable.sh
@@ -13,6 +13,7 @@ declare -ar PROJECT_NAMES=(
"add_to_app/multiple_flutters/multiple_flutters_module"
"add_to_app/plugin/flutter_module_using_plugin"
"add_to_app/prebuilt_module/flutter_module"
+ "android_splash_screen"
"animations"
"experimental/desktop_photo_search"
"experimental/federated_plugin/federated_plugin"