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
.
- In
ControlCatalog.Android
app inMainActivity
class modifyActivity
attribute: addLaunchMode = LaunchMode.SingleTask
. This is necessary to ensure that the application does not restart every time at switch. - 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);
});
}
- In
SafeAreaDemo.Android
app inMainActivity
class modifyActivity
attribute: addLaunchMode = LaunchMode.SingleTask
. - 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);
});
}
- Deploy both apps on device.
- Launch any of them.
After switching between apps a few times, one or both of them will stop responding.
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.