AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology

Home Page:https://avaloniaui.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Android app randomly stops responding when switching to and from another app

zabolotnev opened this issue · comments

Describe the bug

We have an Avalonia app calling another third-party app. This call is made by the Android Application.Context.StartActivity(intent); method. When the third-party app finishes its work, it calls us in the same way. At this moment, our app appears on the screen, but does not respond. This happens randonly, but often enough to be a problem.

To Reproduce

To reproduce, we need two applications calling each other. The Samples catalog contains ControlCatalog.Android and SafeAreaDemo.Android.

  1. In ControlCatalog.Android app in MainActivity class modify Activity attribute: add LaunchMode = LaunchMode.SingleTask. This is necessary to ensure that the application does not restart every time at switch.
  2. In this class add:
        protected override void OnResume()
        {
            base.OnResume();
            Task.Run(async () =>
            {
                await Task.Delay(1000); // simulate some work
                var intent = global::Android.App.Application.Context.PackageManager
                    .GetLaunchIntentForPackage("com.avalonia.safeareademo");
                intent.AddCategory(global::Android.Content.Intent.CategoryDefault);
                global::Android.App.Application.Context.StartActivity(intent);
            });
        }
  1. In SafeAreaDemo.Android app in MainActivity class modify Activity attribute: add LaunchMode = LaunchMode.SingleTask.
  2. In this class add:
        protected override void OnResume()
        {
            base.OnResume();
            Task.Run(async () =>
            {
                await Task.Delay(1000); // simulate some work
                var intent = global::Android.App.Application.Context.PackageManager
                    .GetLaunchIntentForPackage("com.Avalonia.ControlCatalog");
                intent.AddCategory(global::Android.Content.Intent.CategoryDefault);
                global::Android.App.Application.Context.StartActivity(intent);
            });
        }
  1. Deploy both apps on device.
  2. Launch any of them.

After switching between apps a few times, one or both of them will stop responding.

2

Expected behavior

Applications are constantly switching.

Avalonia version

11.0.7

OS

Android

Additional context

I did some debugging to find the problematic code. The problem is in src/Android/Avalonia.Android/AvaloniaView.cs:

изображение

The first thing that catches your eye is the resource leak. The void OnVisibilityChanged(bool isVisible) method is called twice. From the public override void OnVisibilityAggregated and from the protected override void OnVisibilityChanged. The first time it is called, the ChoreographerTimer subscribes to the view and creates an IDisposable object to stop the timer.

_timerSubscription = timer.SubscribeView(this);

When called a second time, the previous timer overwritten without disposing. The timer remains in memory until it is disposed by the GC.

But this doesn't solve the problem. The problem is that the operating system does not always call these methods. Some times it calls MainActivity.OnResume, display the app, but does not call either OnVisibilityAggregated or OnVisibilityChanged. I don't know why, but the trace shows it. In this case, timer.SubscribeView(this) is not called at all, the render timer does not start and the appication hangs.

An additional call to OnVisibilityChanged from MainActivity.OnResume along with checking for double calls will fix the problem. I'll try to submit a PR today.