Xamarin.Android Widget not working when app is closed

Forsaken 21 Reputation points
2021-03-05T15:25:40.047+00:00

I have made a Xamarin.Android Widget with a Button and TextView.

Currently, the widget does not update the TextView when the Button is pressed when the app is not open. However, if the app is in the background, then pressing the Button will update the TextView.

public class WidgetClass : AppWidgetProvider, IUpdateDataService
{
    public static String SaveClick = "Save Product";

    public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
    {
        var me = new ComponentName(context, Java.Lang.Class.FromType(typeof(WidgetClass)).Name);
        appWidgetManager.UpdateAppWidget(me, BuildRemoteViews(context, appWidgetIds));
    }

    private RemoteViews BuildRemoteViews(Context context, int[] appWidgetIds)
    {
        var widgetView = new RemoteViews(context.PackageName, Resource.Layout.widget);
        UpdateData(widgetView);
        RegisterClicks(context, appWidgetIds, widgetView);
        return widgetView;
    }

    private void UpdateData(RemoteViews widgetView)
    {
        CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
        widgetView.SetTextViewText(Resource.Id.textView1, "Last Product: " + App.latestProduct.ProductSaveTime.ToString("g", currentCulture));
    }

    private void RegisterClicks(Context context, int[] appWidgetIds, RemoteViews widgetView)
    {
        var intent = new Intent(context, typeof(WidgetClass));
        intent.SetAction(AppWidgetManager.ActionAppwidgetUpdate);
        intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, appWidgetIds);

        widgetView.SetOnClickPendingIntent(Resource.Id.buttonSave, GetPendingSelfIntent(context, SaveClick));
    }

    private PendingIntent GetPendingSelfIntent(Context context, string action)
    {
        var intent = new Intent(context, typeof(WidgetClass));
        intent.SetAction(action);
        return PendingIntent.GetBroadcast(context, 0, intent, 0);
    }

    public override void OnReceive(Context context, Intent intent)
    {
        base.OnReceive(context, intent);

        if (SaveClick.Equals(intent.Action))
        {
              Product product = new Product
              {           
                  ProductSaveTime = DateTime.Now       
              }; 

            App.latestProduct = product; 

            RemoteViews remoteViews = new RemoteViews(context.PackageName, Resource.Layout.widget);
            UpdateData(remoteViews);
            AppWidgetManager appWidgetManager = AppWidgetManager.GetInstance(context);
            ComponentName componentName = new ComponentName(context, Java.Lang.Class.FromType(typeof(WidgetClass)).Name);
            appWidgetManager.UpdateAppWidget(componentName, remoteViews);
        }
   }

   public void UpdateWidgetUI()
    {
        var widgetView = new RemoteViews(MainActivity.Instance.PackageName, Resource.Layout.widget);
        UpdateData(widgetView);

        AppWidgetManager appWidgetManager = AppWidgetManager.GetInstance(MainActivity.Instance);
        ComponentName componentName = new ComponentName(MainActivity.Instance, Java.Lang.Class.FromType(typeof(WidgetClass)).Name);
        appWidgetManager.UpdateAppWidget(componentName, widgetView);
    }
}

App.cs:

public static Product latestProduct;

Is it possible to make the Button function when the app is not running?

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,294 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,245 questions
0 comments No comments
{count} votes

Accepted answer
  1. JarvanZhang 23,936 Reputation points
    2021-03-08T02:02:29.177+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    Is it possible to make the Button function when the app is not running

    Starting in Android 8.0 (API level 26), an Android application no longer have the ability to run freely in the background. Try using the foreground sevice by starting a foregroud notification to keep the widget working even when it is closed.

       [Service(Enabled = true)]  
       public class MyService : Service  
       {  
           private Handler handler;  
           private Action runnable;  
           private bool isStarted;  
           ...  
           public override void OnCreate()  
           {  
               base.OnCreate();  
         
               handler = new Handler();  
               //here is what you want to do always, i just want to push a notification every 5 seconds here  
               runnable = new Action(() =>  
               {  
                   if (isStarted)  
                   {  
                       DispatchNotification();  
                       handler.PostDelayed(runnable, 5000);  
                   }  
               });  
           }  
           ...  
       }  
    

    Similar issue: https://stackoverflow.com/questions/60028587/background-service-with-isolated-process-in-xamarin-forms/60032046

    Best Regards,

    Jarvan Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. B Martin 21 Reputation points
    2021-04-13T11:13:36.847+00:00

    @Forsaken , have you had any success yet? From what I've research, we have to use a service as a response to the button click, but the button click receive is still in the AppWidgetProvider. Not sure. I also learned that for auto update we have to use JobIntentService and not just Service, even though we still use Service above the class:

       [Service(Label = "WeatherWidgetJobIntentServiceL", Permission = "android.permission.BIND_JOB_SERVICE", Exported = true)]  
        public class WeatherWidgetJobIntentServiceL : JobIntentService  
        {  
    }         
    

    Please message me at https://forums.xamarin.com/profile/BillyMartin and maybe we can work through this together. Android app widgets are important and I can't believe Xamarin Forms has dropped the ball on this and not made it simple to make an App Widget.

    0 comments No comments