Search code examples
c#androidasync-awaitxamarin.android

Xamarin.Android : start an activity and wait for the result


I need to start an activity to ask the user to grant the app battery saving exemption. The user must respond yes to be able to continue:

Here is the -buggy- code I have so far:

   PowerManager pm = (PowerManager)Android.App.Application.Context.GetSystemService(Context.PowerService);
        while (!pm.IsIgnoringBatteryOptimizations(this.ApplicationContext.PackageName))
        {
            IPopupService popupService = Locator.GetSharedInstance<IPopupService>();
            await popupService.DisplayAlertAsync(
                BusinessResources.GoToPowerSettingsTitle,
                BusinessResources.GoToPowerSettingsMessage,
                BusinessResources.Ok).ConfigureAwait(true);
            using (var intent = new Intent(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations, Android.Net.Uri.Parse("package:" + Forms.Context.PackageName)))
            {
                Forms.Context.StartActivity(intent);
            }
        }

Because StartActivity won't wait, I'll ask the user once more than needed.

Now I've searched for a possible solution and found ActivityTask and ActivityController.

I am confused right now. Which one should I use, provided that Xamarin Forms is on the way?


Solution

  • All right, I solved my problem by awaiting an AsyncAutoResetEvent after launching the activity:

    An event is defined as well as a handshake value:

       private AsyncAutoResetEvent dozeStandby;
       private int dozeStandbyHandshake = nameof(dozeStandbyHandshake).GetHashCode(StringComparison.InvariantCultureIgnoreCase);
    

    During the activity creation, I'm prompting the user to allow the settings. Because I'm using StartActivityForResult, OnActivityResult will be called when the prompt activity finishes:

        protected override async void OnCreate(Bundle bundle)
        {
            dozeStandby = new AsyncAutoResetEvent();
    
            PowerManager pm = (PowerManager)Android.App.Application.Context.GetSystemService(Context.PowerService);
            while (!pm.IsIgnoringBatteryOptimizations(this.ApplicationContext.PackageName))
            {
                  IPopupService popupService = Locator.GetSharedInstance<IPopupService>();
                  await popupService.DisplayAlertAsync(
                            BusinessResources.GoToPowerSettingsTitle,
                            BusinessResources.GoToPowerSettingsMessage,
                            BusinessResources.Ok).ConfigureAwait(true);
                  using (var intent = new Intent(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations, Android.Net.Uri.Parse("package:" + Android.App.Application.Context.PackageName)))
                  {
                      this.StartActivityForResult(intent, dozeStandbyHandshake);
                      await this.dozeStandby.WaitAsync().ConfigureAwait(true);
                  }
             }
        }
    

    In here I check the handshake to set the event.

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            if (requestCode == dozeStandbyHandshake)
            {
                this.dozeStandby.Set();
            }
        }