3

I'm trying to port following code to xamarin.android from xamarin.iOS:

   public HomeView() : base(nameof(HomeView), null) {
        NSNotificationCenter.DefaultCenter.AddObserver(UIApplication.WillEnterForegroundNotification, (NSNotification not) => {
            if(NavigationController.TopViewController is HomeView)
                ScrollToCurrentDay();
        });

        DispatchQueue.MainQueue.DispatchAsync(() => {
            ScrollToCurrentDay();
        });
    }

How do you call a function whenever a view loads for the first time or when the app enters foreground? I tried using a BroadcastReceiver see here. Is there a simpler and shorter way of doing it?

julian.a
  • 1,163
  • 2
  • 9
  • 21
  • Did you try OnCreate() and OnResume() lifecycle methods of andoid activity? OnCreate() is called when Activity is first created and OnResume() is called when your Activity comes to Foreground from the Background. Check this : https://www.tutorialspoint.com/xamarin/xamarin_android_activity_lifecycle.htm – MilanG Oct 23 '17 at 16:44
  • Are you using these project with `Xamarin.Forms` ? – York Shen Oct 24 '17 at 02:30
  • @MilanG Thanks, I'm using those methods. It's not exactly what I was looking for but it's working. – julian.a Oct 24 '17 at 11:13
  • @YorkShen-MSFT Xamarin.iOS and Xamarin.Android with MVVM Cross. – julian.a Oct 24 '17 at 11:13

1 Answers1

1

Call specific code on entering app foreground

As @MilanG said, the Activity's OnResume() method will be called when your app comes foreground from background :

protected override void OnResume()
{
    base.OnResume();
    ScrollToCurrentDay();
}

As the document said :

When the activity enters the Started state, the system invokes this callback. The onStart() call makes the activity visible to the user, as the app prepares for the activity to enter the foreground and become interactive.

However, the Activity's OnResume() method are also be called when this Activity is open by another Activity.

There isn't any direct approach to get the application status while in the background or foreground, you need add a listener to the Activity's life circle.

Solution 1 :

You could create a BaseActivity to mirror the Activity lifecycle callbacks, every other Activity have to extend this BaseActivity. Then you can track when your activities through their lifecycle and react accordingly. For more detail information, you could read this document. Here is an example :

public abstract class BaseActivity : AppCompatActivity
{
    public static bool isAppWentToBg = false;
    public static bool isWindowFocused = false;
    public static bool isMenuOpened = false;
    public static bool isBackPressed = false;

    protected override void OnStart()
    {
        applicationWillEnterForeground();
        base.OnStart();
    }

    private void applicationWillEnterForeground()
    {
        if (isAppWentToBg)
        {
            isAppWentToBg = false;
            Toast.MakeText(ApplicationContext, "App is in foreground", ToastLength.Short).Show();
        }
    }

    protected override void OnStop()
    {
        base.OnStop();
        applicationdidenterbackground();
    }

    public void applicationdidenterbackground()
    {
        if (!isWindowFocused)
        {
            isAppWentToBg = true;
            Toast.MakeText(ApplicationContext, "App is Going to Background", ToastLength.Short).Show();
        }
    }

    //Called when the current Window of the activity gains or loses focus.
    public override void OnWindowFocusChanged(bool hasFocus)
    {
        isWindowFocused = hasFocus;

        if (isBackPressed && !hasFocus)
        {
            isBackPressed = false;
            isWindowFocused = true;
        }

        base.OnWindowFocusChanged(hasFocus);
    }

    public override void OnBackPressed()
    {
        base.OnBackPressed();
        if (this.GetType() ==  typeof(MainActivity)) {

        } else {
            isBackPressed = true;
        }

    }
}

Solution 2 :

You could register a ActivityLifecycleCallbacks to mirror all the Activity lifecycle callbacks, since you using MvvmCross, it is recommended to use this solution :

[Application]
public class MyApplication : Application
{
    public MyApplication(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip)
    {
    }

    public override void OnCreate()
    {
        base.OnCreate();
        RegisterActivityLifecycleCallbacks(new AppLifecycleListener());
    }
}

public class AppLifecycleListener : Java.Lang.Object, Application.IActivityLifecycleCallbacks
{
    private int numStarted = 0;

    ...

    public void OnActivityStarted(Activity activity)
    {
        if (numStarted == 0)
        {
            // app went to foreground
            Toast.MakeText(Android.App.Application.Context, "App is in foreground", ToastLength.Short).Show();
        }
        numStarted++;
    }

    public void OnActivityStopped(Activity activity)
    {
        numStarted--;
        if (numStarted == 0)
        {
            // app went to background
            Toast.MakeText(Android.App.Application.Context, "App is Going to Background", ToastLength.Short).Show();
        }
    }
}
York Shen
  • 9,014
  • 1
  • 16
  • 40
  • I'll let you know in ~5days. I'm currently on vacation. – julian.a Oct 30 '17 at 13:59
  • I think my co-worker used another solution. I showed it to him and he said it's harder to solve for his very specific problem. Thanks for your help though. In the beginning he did implement it in a similar way, so I'm pretty sure it's working for most cases. – julian.a Nov 10 '17 at 13:27