mirror of
https://github.com/apache/cordova-android.git
synced 2026-05-30 00:00:04 +08:00
feat!: android 12 splash screen (#1441)
* chore!: remove old splashscreen logic * feat(splashscreen): add backwards compatibility * chore: remove unused method * chore: prefix splashscreen_background with cdv_ * feat: support android 12 splashscreen api configs * feat: improve & refactor the logic for android splashscreen api 12 * feat: splashscreen copy image resources * feat: splashscreen branding image & xml cleanup * fix: splashscreen cleanup & branding conditions * fix: splashscreen @color usage * feat: update default Apache Cordova splash screen * chore: add missing asf header * fix: splashscreen image size * chore: use Theme.SplashScreen.IconBackground as default parent to support windowSplashScreenIconBackgroundColor * fix: center default test image by correct pivot * fix: fs-extra copySync * feat: re-add AutoHideSplashScreen and SplashScreenDelay preference support * chore: move splashscreen into CordovaActivity * feat: support splashscreen.hide & centralize to SplashScreenPlugin * chore: cleanup SplashScreenPlugin * feat: support fade, default auto hide on onPageFinished, support delays, refactor * refactor: cleanup splash screen * refactor: cleanup remove unused import * chore: add show method as unsupported * test: create a spy on updateProjectSplashScreen * style: add ending new line * chore: improve logging to warn when image path is missing * chore: split windowSplashScreenAnimatedIcon and windowSplashScreenBrandingImage case and added branding warning * chore: improve when to display warning * fix: add splashscreen dependency to app as well * chore: move the core-splashscreen dep lower Co-authored-by: Niklas Merz <niklasmerz@linux.com>
This commit is contained in:
@@ -80,6 +80,7 @@ android {
|
||||
dependencies {
|
||||
implementation "androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
|
||||
implementation "androidx.webkit:webkit:${cordovaConfig.ANDROIDX_WEBKIT_VERSION}"
|
||||
implementation "androidx.core:core-splashscreen:${cordovaConfig.ANDROIDX_CORE_SPLASHSCREEN_VERSION}"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"KOTLIN_VERSION": "1.5.21",
|
||||
"ANDROIDX_APP_COMPAT_VERSION": "1.4.2",
|
||||
"ANDROIDX_WEBKIT_VERSION": "1.4.0",
|
||||
"ANDROIDX_CORE_SPLASHSCREEN_VERSION": "1.0.0-rc01",
|
||||
"GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION": "4.3.10",
|
||||
"IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED": false,
|
||||
"IS_GRADLE_PLUGIN_KOTLIN_ENABLED": false
|
||||
|
||||
@@ -76,6 +76,14 @@ public class ConfigXmlParser {
|
||||
)
|
||||
);
|
||||
|
||||
pluginEntries.add(
|
||||
new PluginEntry(
|
||||
SplashScreenPlugin.PLUGIN_NAME,
|
||||
"org.apache.cordova.SplashScreenPlugin",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
parse(action.getResources().getXml(id));
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
|
||||
/**
|
||||
* This class is the main Android activity that represents the Cordova
|
||||
@@ -98,11 +99,16 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
protected ArrayList<PluginEntry> pluginEntries;
|
||||
protected CordovaInterfaceImpl cordovaInterface;
|
||||
|
||||
private SplashScreen splashScreen;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
// Handle the splash screen transition.
|
||||
splashScreen = SplashScreen.installSplashScreen(this);
|
||||
|
||||
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
|
||||
loadConfig();
|
||||
|
||||
@@ -125,8 +131,6 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
// (as was the case in previous cordova versions)
|
||||
if (!preferences.getBoolean("FullscreenNotImmersive", false)) {
|
||||
immersiveMode = true;
|
||||
// The splashscreen plugin needs the flags set before we're focused to prevent
|
||||
// the nav and title bars from flashing in.
|
||||
setImmersiveUiVisibility();
|
||||
} else {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
@@ -153,6 +157,9 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
}
|
||||
cordovaInterface.onCordovaInit(appView.getPluginManager());
|
||||
|
||||
// Setup the splash screen based on preference settings
|
||||
cordovaInterface.pluginManager.postMessage("setupSplashScreen", splashScreen);
|
||||
|
||||
// Wire the hardware volume controls to control media if desired.
|
||||
String volumePref = preferences.getString("DefaultVolumeStream", "");
|
||||
if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
|
||||
@@ -526,5 +533,4 @@ public class CordovaActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you 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 org.apache.cordova;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
import androidx.core.splashscreen.SplashScreenViewProvider;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
@SuppressLint("LongLogTag")
|
||||
public class SplashScreenPlugin extends CordovaPlugin {
|
||||
static final String PLUGIN_NAME = "CordovaSplashScreenPlugin";
|
||||
|
||||
// Default config preference values
|
||||
private static final boolean DEFAULT_AUTO_HIDE = true;
|
||||
private static final int DEFAULT_DELAY_TIME = -1;
|
||||
private static final boolean DEFAULT_FADE = true;
|
||||
private static final int DEFAULT_FADE_TIME = 500;
|
||||
|
||||
// Config preference values
|
||||
/**
|
||||
* @param boolean autoHide to auto splash screen (default=true)
|
||||
*/
|
||||
private boolean autoHide;
|
||||
/**
|
||||
* @param int delayTime in milliseconds (default=-1)
|
||||
*/
|
||||
private int delayTime;
|
||||
/**
|
||||
* @param int fade to fade out splash screen (default=true)
|
||||
*/
|
||||
private boolean isFadeEnabled;
|
||||
/**
|
||||
* @param int fadeDuration fade out duration in milliseconds (default=500)
|
||||
*/
|
||||
private int fadeDuration;
|
||||
|
||||
// Internal variables
|
||||
/**
|
||||
* @param boolean keepOnScreen flag to determine if the splash screen remains visible.
|
||||
*/
|
||||
private boolean keepOnScreen = true;
|
||||
|
||||
@Override
|
||||
protected void pluginInitialize() {
|
||||
// Auto Hide & Delay Settings
|
||||
autoHide = preferences.getBoolean("AutoHideSplashScreen", DEFAULT_AUTO_HIDE);
|
||||
delayTime = preferences.getInteger("SplashScreenDelay", DEFAULT_DELAY_TIME);
|
||||
LOG.d(PLUGIN_NAME, "Auto Hide: " + autoHide);
|
||||
if (delayTime != DEFAULT_DELAY_TIME) {
|
||||
LOG.d(PLUGIN_NAME, "Delay: " + delayTime + "ms");
|
||||
}
|
||||
|
||||
// Fade & Fade Duration
|
||||
isFadeEnabled = preferences.getBoolean("FadeSplashScreen", DEFAULT_FADE);
|
||||
fadeDuration = preferences.getInteger("FadeSplashScreenDuration", DEFAULT_FADE_TIME);
|
||||
LOG.d(PLUGIN_NAME, "Fade: " + isFadeEnabled);
|
||||
if (isFadeEnabled) {
|
||||
LOG.d(PLUGIN_NAME, "Fade Duration: " + fadeDuration + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(
|
||||
String action,
|
||||
JSONArray args,
|
||||
CallbackContext callbackContext
|
||||
) throws JSONException {
|
||||
if (action.equals("hide") && autoHide == false) {
|
||||
/*
|
||||
* The `.hide()` method can only be triggered if the `splashScreenAutoHide`
|
||||
* is set to `false`.
|
||||
*/
|
||||
keepOnScreen = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
callbackContext.success();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onMessage(String id, Object data) {
|
||||
switch (id) {
|
||||
case "setupSplashScreen":
|
||||
setupSplashScreen((SplashScreen) data);
|
||||
break;
|
||||
|
||||
case "onPageFinished":
|
||||
attemptCloseOnPageFinished();
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setupSplashScreen(SplashScreen splashScreen) {
|
||||
// Setup Splash Screen Delay
|
||||
splashScreen.setKeepOnScreenCondition(() -> keepOnScreen);
|
||||
|
||||
// auto hide splash screen when custom delay is defined.
|
||||
if (autoHide && delayTime != DEFAULT_DELAY_TIME) {
|
||||
Handler splashScreenDelayHandler = new Handler();
|
||||
splashScreenDelayHandler.postDelayed(() -> keepOnScreen = false, delayTime);
|
||||
}
|
||||
|
||||
// auto hide splash screen with default delay (-1) delay is controlled by the
|
||||
// `onPageFinished` message.
|
||||
|
||||
// If auto hide is disabled (false), the hiding of the splash screen must be determined &
|
||||
// triggered by the front-end code with the `navigator.splashscreen.hide()` method.
|
||||
|
||||
// Setup the fade
|
||||
splashScreen.setOnExitAnimationListener(new SplashScreen.OnExitAnimationListener() {
|
||||
@Override
|
||||
public void onSplashScreenExit(@NonNull SplashScreenViewProvider splashScreenViewProvider) {
|
||||
View splashScreenView = splashScreenViewProvider.getView();
|
||||
|
||||
splashScreenView
|
||||
.animate()
|
||||
.alpha(0.0f)
|
||||
.setDuration(isFadeEnabled ? fadeDuration : 0)
|
||||
.setStartDelay(isFadeEnabled ? 0 : fadeDuration)
|
||||
.setInterpolator(new AccelerateInterpolator())
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
splashScreenViewProvider.remove();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void attemptCloseOnPageFinished() {
|
||||
if (autoHide && delayTime == DEFAULT_DELAY_TIME) {
|
||||
keepOnScreen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user