Mvvmcross: [Android] AppStart deadlocks

Created on 22 Jan 2019  路  6Comments  路  Source: MvvmCross/MvvmCross

馃悰 Bug Report

MvvmCross Android apps are not correctly resuming after Android or the user terminates the process. The app freezes displaying a white screen after attempting to resume the terminated process. This bug can be reproduced using the Playground.Droid project.

The following messages are showing up in logcat before Playground.Droid freezes on the white screen:

01-22 11:41:27.516: W/Playground.Core.ViewModels.RootViewModel(12571): [Warning] Testing log
01-22 11:41:27.889: W/Playground.Core.ViewModels.RootViewModel(12571): [Warning] Testing log
01-22 11:41:27.978: W/MvvmCross.Logging.MvxLog(12571): [Warning] Cannot Resolve current top activity

Attempting the same scenario with Playground.Droid.Forms doesn't result in the freeze/white screen. I noticed some differences between Playground.Droid.Forms and Playground.Droid while testing this scenario:

  • Playground.Droid.Forms only logs "Testing log" once while Playground.Droid logs "Testing log" twice. It seems like this means RootViewModel is being loaded twice when Playground.Droid is resuming.
  • Playground.Droid.Forms doesn't have a problem finding the top activity while Playground.Droid does.

Expected behavior

The app should resume correctly when restored via the overview (square) button after the process has been killed.

Reproduction steps

  1. Run Playground.Droid directly on the phone/emulator without debugging. Wait for the splash screen to go away.
  2. Send Playground.Droid to the background by pressing the home button.
  3. Use Android Device Monitor to kill the com.mvvmcross.playground process by clicking the Stop Process button.
  4. Tap the Android overview (square) button and select Playground.Droid to attempt to restore the app.
  5. At this point the white screen appears, the back + overview buttons don't respond much at all. The app must be force closed by the user.

Configuration

Version: 6.2.x (6.2.2 NuGet & develop branch of 6.2.3)

Platform:

  • [ ] :iphone: iOS
  • [x] :robot: Android
  • [ ] :checkered_flag: WPF
  • [ ] :earth_americas: UWP
  • [ ] :apple: MacOS
  • [ ] :tv: tvOS
  • [ ] :monkey: Xamarin.Forms
bug up-for-grabs

Most helpful comment

Here's a workaround for anyone affected by this problem:

public class SplashActivity : MvvmCross.Droid.Support.V7.AppCompat.MvxSplashScreenAppCompatActivity
{
    public SplashActivity() : base(Resource.Layout.activity_splash)
    {
    }

    protected override async Task RunAppStartAsync(Bundle bundle)
    {
        if (MvvmCross.Mvx.IoCProvider.TryResolve(out IMvxAppStart startup))
        {
            await startup.StartAsync(GetAppStartHint(bundle));
            if (!startup.IsStarted)
            {
                await startup.StartAsync(GetAppStartHint(bundle));
            }
            else
            {
                Finish();
            }
        }
    }
}
public abstract class BaseActivity<TViewModel> : MvxAppCompatActivity<TViewModel> where TViewModel : MvxViewModel
{
    protected override void RunAppStart(Bundle bundle)
    {
    }
}

The app no longer deadlocks when the process is restarted by the Android OS after the workaround is implemented.

All 6 comments

For what it's worth, the changes in PR #3214 fixes this deadlock.

I have an older Samsung SGH-I337 phone that also triggers this AppStart deadlock when I try to take a picture using StartActivityForResult(new Intent(MediaStore.ActionImageCapture), CAMERA_IMAGE); I see "AppStart: Application Startup - On UI thread" in the output window then the process deadlocks. I'm able to reproduce this while debugging and see the main thread is in this state:

System.Threading.Monitor.Monitor_wait()
0xFFFFFFFFFFFFFFFF in System.Threading.Monitor.Monitor_wait
0x31 in System.Threading.Monitor.ObjWait
0x11 in System.Threading.Monitor.Wait
0x3 in System.Threading.Monitor.Wait
0x14A in System.Threading.ManualResetEventSlim.Wait
0x30 in System.Threading.Tasks.Task.SpinThenBlockingWait
0x6C in System.Threading.Tasks.Task.InternalWait
0x13 in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
0x9 in System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
0x6 in System.Runtime.CompilerServices.TaskAwaiter.GetResult
0xF in MvvmCross.ViewModels.MvxAppStart.Start at C:\projects\mvvmcross\MvvmCross\ViewModels\MvxAppStart.cs:28,13
0x1B in MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatActivity.RunAppStart at C:\projects\mvvmcross\MvvmCross.Android.Support\V7.AppCompat\MvxAppCompatActivity.cs:101,17
0x22 in MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatActivity.OnCreate at C:\projects\mvvmcross\MvvmCross.Android.Support\V7.AppCompat\MvxAppCompatActivity.cs:93,17
0x3 in .Views.BaseActivity.OnCreate at E:\src\PnD Mobile\Client\\Views\Base\BaseActivity.cs:20,13
0x3 in .Views.MainActivity.OnCreate at E:\src\PnD Mobile\Client\\Views\Activities\MainActivity.cs:26,13
0x13 in Android.App.Activity.n_OnCreate_Landroid_os_Bundle_
0x17 in object.11

This happens with 6.2.2 and 25.4.0-alpha.2863 on NuGet.

Been getting this issue too specially after app has been resumed after it has been in the background for a while.

Here's a workaround for anyone affected by this problem:

public class SplashActivity : MvvmCross.Droid.Support.V7.AppCompat.MvxSplashScreenAppCompatActivity
{
    public SplashActivity() : base(Resource.Layout.activity_splash)
    {
    }

    protected override async Task RunAppStartAsync(Bundle bundle)
    {
        if (MvvmCross.Mvx.IoCProvider.TryResolve(out IMvxAppStart startup))
        {
            await startup.StartAsync(GetAppStartHint(bundle));
            if (!startup.IsStarted)
            {
                await startup.StartAsync(GetAppStartHint(bundle));
            }
            else
            {
                Finish();
            }
        }
    }
}
public abstract class BaseActivity<TViewModel> : MvxAppCompatActivity<TViewModel> where TViewModel : MvxViewModel
{
    protected override void RunAppStart(Bundle bundle)
    {
    }
}

The app no longer deadlocks when the process is restarted by the Android OS after the workaround is implemented.

Thanks @tbalcom

I'm closing this because it was fixed when #3214 was merged.

Was this page helpful?
0 / 5 - 0 ratings