2727import android .util .Log ;
2828import android .view .SurfaceView ;
2929import android .view .ViewGroup ;
30+ import android .view .View ;
3031import android .widget .ImageView ;
3132import android .widget .Toast ;
33+ import android .content .res .Resources .NotFoundException ;
3234
3335import org .libsdl .app .SDLActivity ;
3436
@@ -61,7 +63,7 @@ protected void onCreate(Bundle savedInstanceState) {
6163 Log .v (TAG , "Did super onCreate" );
6264
6365 this .mActivity = this ;
64- this .showLoadingScreen ();
66+ this .showLoadingScreen (this . getLoadingScreen () );
6567
6668 new UnpackFilesTask ().execute (getAppRoot ());
6769 }
@@ -121,7 +123,7 @@ protected void onPostExecute(String result) {
121123 // removed the loading screen. However, we still need it to
122124 // show until the app is ready to render, so pop it back up
123125 // on top of the SDL view.
124- mActivity .showLoadingScreen ();
126+ mActivity .showLoadingScreen (getLoadingScreen () );
125127
126128 String app_root_dir = getAppRoot ();
127129 if (getIntent () != null && getIntent ().getAction () != null &&
@@ -338,6 +340,7 @@ public static void stop_service() {
338340
339341 /** Loading screen view **/
340342 public static ImageView mImageView = null ;
343+ public static View mLottieView = null ;
341344 /** Whether main routine/actual app has started yet **/
342345 protected boolean mAppConfirmedActive = false ;
343346 /** Timer for delayed loading screen removal. **/
@@ -404,11 +407,11 @@ public void run() {
404407 public void removeLoadingScreen () {
405408 runOnUiThread (new Runnable () {
406409 public void run () {
407- if ( PythonActivity . mImageView != null &&
408- PythonActivity . mImageView .getParent () != null ) {
409- ((ViewGroup )PythonActivity . mImageView . getParent ()).removeView (
410- PythonActivity . mImageView ) ;
411- PythonActivity . mImageView = null ;
410+ View view = mLottieView != null ? mLottieView : mImageView ;
411+ if ( view != null && view .getParent () != null ) {
412+ ((ViewGroup )view . getParent ()).removeView (view );
413+ mLottieView = null ;
414+ mImageView = null ;
412415 }
413416 }
414417 });
@@ -430,65 +433,97 @@ public String getEntryPoint(String search_dir) {
430433 return "main.py" ;
431434 }
432435
433- protected void showLoadingScreen () {
436+ protected void showLoadingScreen (View view ) {
437+ try {
438+ if (mLayout == null ) {
439+ setContentView (view );
440+ } else if (view .getParent () == null ) {
441+ mLayout .addView (view );
442+ }
443+ } catch (IllegalStateException e ) {
444+ // The loading screen can be attempted to be applied twice if app
445+ // is tabbed in/out, quickly.
446+ // (Gives error "The specified child already has a parent.
447+ // You must call removeView() on the child's parent first.")
448+ }
449+ }
450+
451+ protected View getLoadingScreen () {
434452 // load the bitmap
435453 // 1. if the image is valid and we don't have layout yet, assign this bitmap
436454 // as main view.
437455 // 2. if we have a layout, just set it in the layout.
438456 // 3. If we have an mImageView already, then do nothing because it will have
439457 // already been made the content view or added to the layout.
440458
441- if (mImageView == null ) {
442- int presplashId = this .resourceManager .getIdentifier ("presplash" , "drawable" );
443- InputStream is = this .getResources ().openRawResource (presplashId );
444- Bitmap bitmap = null ;
459+ if (mLottieView != null || mImageView != null ) {
460+ // we already have a splash screen
461+ return mLottieView != null ? mLottieView : mImageView ;
462+ }
463+
464+ // first try to load the lottie one
465+ try {
466+ mLottieView = getLayoutInflater ().inflate (
467+ this .resourceManager .getIdentifier ("lottie" , "layout" ),
468+ mLayout ,
469+ false
470+ );
445471 try {
446- bitmap = BitmapFactory .decodeStream (is );
447- } finally {
448- try {
449- is .close ();
450- } catch (IOException e ) {};
472+ if (mLayout == null ) {
473+ setContentView (mLottieView );
474+ } else if (PythonActivity .mLottieView .getParent () == null ) {
475+ mLayout .addView (mLottieView );
476+ }
477+ } catch (IllegalStateException e ) {
478+ // The loading screen can be attempted to be applied twice if app
479+ // is tabbed in/out, quickly.
480+ // (Gives error "The specified child already has a parent.
481+ // You must call removeView() on the child's parent first.")
451482 }
452-
453- mImageView = new ImageView (this );
454- mImageView .setImageBitmap (bitmap );
455-
456- /*
457- * Set the presplash loading screen background color
458- * https://developer.android.com/reference/android/graphics/Color.html
459- * Parse the color string, and return the corresponding color-int.
460- * If the string cannot be parsed, throws an IllegalArgumentException exception.
461- * Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
462- * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow',
463- * 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia',
464- * 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'.
465- */
466- String backgroundColor = resourceManager .getString ("presplash_color" );
467- if (backgroundColor != null ) {
468- try {
469- mImageView .setBackgroundColor (Color .parseColor (backgroundColor ));
470- } catch (IllegalArgumentException e ) {}
471- }
472- mImageView .setLayoutParams (new ViewGroup .LayoutParams (
473- ViewGroup .LayoutParams .FILL_PARENT ,
474- ViewGroup .LayoutParams .FILL_PARENT ));
475- mImageView .setScaleType (ImageView .ScaleType .FIT_CENTER );
483+ return mLottieView ;
484+ }
485+ catch (NotFoundException e ) {
486+ Log .v ("SDL" , "couldn't find lottie layout or animation, trying static splash" );
476487 }
477488
489+ // try to load the static image then
490+ int presplashId = this .resourceManager .getIdentifier ("presplash" , "drawable" );
491+ InputStream is = this .getResources ().openRawResource (presplashId );
492+ Bitmap bitmap = null ;
478493 try {
479- if (mLayout == null ) {
480- setContentView (mImageView );
481- } else if (PythonActivity .mImageView .getParent () == null ) {
482- mLayout .addView (mImageView );
483- }
484- } catch (IllegalStateException e ) {
485- // The loading screen can be attempted to be applied twice if app
486- // is tabbed in/out, quickly.
487- // (Gives error "The specified child already has a parent.
488- // You must call removeView() on the child's parent first.")
494+ bitmap = BitmapFactory .decodeStream (is );
495+ } finally {
496+ try {
497+ is .close ();
498+ } catch (IOException e ) {};
489499 }
500+
501+ mImageView = new ImageView (this );
502+ mImageView .setImageBitmap (bitmap );
503+
504+ /*
505+ * Set the presplash loading screen background color
506+ * https://developer.android.com/reference/android/graphics/Color.html
507+ * Parse the color string, and return the corresponding color-int.
508+ * If the string cannot be parsed, throws an IllegalArgumentException exception.
509+ * Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
510+ * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow',
511+ * 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia',
512+ * 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'.
513+ */
514+ String backgroundColor = resourceManager .getString ("presplash_color" );
515+ if (backgroundColor != null ) {
516+ try {
517+ mImageView .setBackgroundColor (Color .parseColor (backgroundColor ));
518+ } catch (IllegalArgumentException e ) {}
519+ }
520+ mImageView .setLayoutParams (new ViewGroup .LayoutParams (
521+ ViewGroup .LayoutParams .FILL_PARENT ,
522+ ViewGroup .LayoutParams .FILL_PARENT ));
523+ mImageView .setScaleType (ImageView .ScaleType .FIT_CENTER );
524+ return mImageView ;
490525 }
491-
526+
492527 @ Override
493528 protected void onPause () {
494529 if (this .mWakeLock != null && mWakeLock .isHeld ()) {
0 commit comments