I have made an Xamarin.Android Widget with a Button and TextView. I have an instance of product (latestProduct) declared in App.cs. A new product is assigned to latestProduct when a new product is added.
The user is able to save a new record by clicking a Button (BtnAdd) on a Xamarin.Forms page. I am trying to update the Widget TextView when the user clicks this Button.
MyPage:
void BtnAdd_Clicked(object sender, EventArgs e) {
Product product = new Product
{
ProductSaveTime = DateTime.Now
};
App.Database.SaveProduct(product);
App.latestProduct = product;
DependencyService.Get<IUpdateDataService>().UpdateWidgetUI();
}
App.cs:
public static Product latestProduct;
IUpdateDataService.cs:
public interface IUpdateDataService
{
void UpdateWidgetUI();
}
WidgetClass.cs:
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(context.PackageName, Resource.Layout.widget);
UpdateData(widgetView);
AppWidgetManager appWidgetManager = AppWidgetManager.GetInstance(context);
ComponentName componentName = new ComponentName(context, Java.Lang.Class.FromType(typeof(WidgetClass)).Name);
appWidgetManager.UpdateAppWidget(componentName, remoteViews);
}
}
When BtnAdd is clicked, how can I use DependecyService to call UpdateData()? The problem I have is 'context' does not exist in the current context in UpdateWidgetUI();
You could make your MainActivity as a static variable.
like:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity Instance;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Instance = this;
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
then you want use the context,you could do like:
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, remoteViews);
}
Related
I have a foreground service with a thread that is continuously checking data from a server.
So the service works well and it doesn't closes when I close the app, but when I start the app again the service creates another thread. Is posible abort the thread of the previous instance?
This is my MainActivity
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static Activity ActivityCurrent { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Window.SetStatusBarColor(Android.Graphics.Color.Rgb(0, 120, 71));
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
System.Diagnostics.Debug.WriteLine("Iniciado");
LoadApplication(new App());
ActivityCurrent = this;
DependencyService.Get<IServicio>().Start();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
This is my service class
[Service(ForegroundServiceType = Android.Content.PM.ForegroundService.TypeDataSync)]
public class Servicio : Service, IServicio
{
Uri link = new Uri(new Url().Dir + "/estado_alarma.php");
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
[return: GeneratedEnum]
Thread refrescar;
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int starId)
{
if (intent.Action == "START_SERVICE")
{
System.Diagnostics.Debug.WriteLine("Se ha iniciado el servicio");
RegisterNotification();
}
else if (intent.Action == "STOP_SERVICE")
{
StopForeground(true);
StopSelfResult(starId);
}
return StartCommandResult.NotSticky;
}
private void RegisterNotification()
{
NotificationChannel channel = new NotificationChannel("ServicioChannel", "Demo de servicio", NotificationImportance.Max);
NotificationManager manager = (NotificationManager)MainActivity.ActivityCurrent.GetSystemService(Context.NotificationService);
manager.CreateNotificationChannel(channel);
Notification notification = new Notification.Builder(this, "ServicioChannel").SetContentTitle("Servicio Trabajando").SetOngoing(true).Build();
StartForeground(200, notification);
_ = IniciarServicio();
}
public void Start()
{
Intent startService = new Intent(MainActivity.ActivityCurrent, typeof(Servicio));
startService.SetAction("START_SERVICE");
MainActivity.ActivityCurrent.StartService(startService);
}
public void Stop()
{
Intent startService = new Intent(MainActivity.ActivityCurrent, typeof(Servicio));
startService.SetAction("STOP_SERVICE");
MainActivity.ActivityCurrent.StartService(startService);
}
public int IniciarServicio()
{
refrescar = new Thread(EsperaAlarmaAsync);
refrescar.Start();
return 1;
}
public async void EsperaAlarmaAsync()
{
WebClient cliente = new WebClient();
byte[] respuesta;
string resultado;
var a = true;
while (a)
{
respuesta = cliente.DownloadData(link);
resultado = System.Text.Encoding.ASCII.GetString(respuesta);
cliente.Dispose();
if (resultado == "Alerta")
{
setNotificationVolumeToMax();
Device.BeginInvokeOnMainThread(() =>
{
App.Current.MainPage = new Alerta();
var powerManager = (PowerManager)GetSystemService(PowerService);
var wakeLock = powerManager.NewWakeLock(WakeLockFlags.ScreenDim | WakeLockFlags.AcquireCausesWakeup, "Ejemplo");
wakeLock.Acquire();
Intent x = new Intent(MainActivity.ActivityCurrent.Intent);
StartActivity(x);
});
a = false;
}
Thread.Sleep(3000);
}
refrescar.Abort();
}
private void setNotificationVolumeToMax()
{
try
{
var audioManager = (AudioManager)GetSystemService(Context.AudioService);
int max_volume = audioManager.GetStreamMaxVolume(Android.Media.Stream.Music);
audioManager.SetStreamVolume(Android.Media.Stream.Music, max_volume, 0);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
When the server return 'Alerta' it opens the app
I am trying to change the text of a TextView an ImageButton click. However, when the button is pressed, the text does not change.
I have tried to use TextView tv = (TextView)findViewById(R.id.textView1);. However, I am not able to use FindViewById because I am working with RemoteViews.
The text of textView1 is set correctly OnUpdate, but does not change when the button is pressed. A button click is correctly registered as the Toast popup is displayed.
class WidgetClass : AppWidgetProvider
{
private Book latestBook;
public static String SaveClick = "Save Book";
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);
SetTextViewText(widgetView);
RegisterClicks(context, appWidgetIds, widgetView);
return widgetView;
}
private void SetTextViewText(RemoteViews widgetView)
{
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
widgetView.SetTextViewText(Resource.Id.textView1, latestBook.lastSaveTime.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))
{
Book book = new Book
{
lastSaveTime = DateTime.Now
};
App.Database.SaveBook(book);
latestBook = book;
Toast.MakeText(context, "New BookAdded", ToastLength.Short).Show();
var widgetView = new RemoteViews(context.PackageName, Resource.Layout.widget);
SetTextViewText(widgetView);
}
}
}
widget.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginRight="0.0dp">
<ImageButton
android:id="#+id/buttonSave"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="65dp"
android:layout_height="65dp"
android:scaleType="fitCenter"/>
<TextView
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_width="135dp"
android:layout_height="wrap_content"
android:id="#+id/textView1"/>
</RelativeLayout>
</LinearLayout>
How can I update the text of textView1 when buttonSave is clicked?
You are creating new remoteview in OnReceive method. You should use existing one. I have updated code. Please check and update me.
class WidgetClass : AppWidgetProvider
{
private Book latestBook;
public static String SaveClick = "Save Book";
RemoteViews remoteView = null;
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);
SetTextViewText(widgetView);
RegisterClicks(context, appWidgetIds, widgetView);
remoteView = widgetView;
return widgetView;
}
private void SetTextViewText(RemoteViews widgetView)
{
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
widgetView.SetTextViewText(Resource.Id.textView1, latestBook.lastSaveTime.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))
{
Book book = new Book
{
lastSaveTime = DateTime.Now
};
App.Database.SaveBook(book);
latestBook = book;
Toast.MakeText(context, "New BookAdded", ToastLength.Short).Show();
SetTextViewText(remoteView);
}
}
}
I want to update my main activity UI in my foreground service with broadcast receiver. In BroadcastReceiver.OnReceive method,I passed the instance of main activity,but it is always nullable. How can I fix it? Many thanks in advance!
In my broadcast receiver:
public override void OnReceive(Context context, Intent intent)
{
Core.Music music = intent.GetParcelableExtra("selectedMusic") as Core.Music;
mMainActivity.mTxtSongName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Title);
mMainActivity.mTxtAuthorName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Author);
System.Threading.ThreadPool.QueueUserWorkItem(o =>
{
string imageUrl = music.Url.Replace(#"\", "").Replace("http", "https");
var task = Core.MusicHelper.GetSongPic(imageUrl, 35, 35);
var pic = task.Result;
if (pic != null)
{
mMainActivity.RunOnUiThread(() =>
{
mMainActivity.mImageViewSongPic.SetImageBitmap(pic);
});
}
});
}
In my service:
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Core.Music music = intent.GetParcelableExtra("selectedMusic") as Core.Music;
BroadcastStarted(music);
//To start the service
return StartCommandResult.NotSticky;
}
In my MainActivity.OnResume:
IntentFilter filter = new IntentFilter();
mReceive = new Service.Boradcast.MusicChangedBroadcastReceiver() { mMainActivity=this};
RegisterReceiver(mReceive,filter);
how do you defined mMainActivity ?
however the simplest example of a reference to MainActivity is to use static
define in your MainActivity OnCreate() method:
public static MainActivity Instance;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
...
Instance = this;
}
then call in your broadcast receiver
public override void OnReceive(Context context, Intent intent)
{
Core.Music music = intent.GetParcelableExtra("selectedMusic") as Core.Music;
MainActivity.Instance.mTxtSongName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Title);
MainActivity.Instance.mTxtAuthorName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Author);
System.Threading.ThreadPool.QueueUserWorkItem(o =>
{
string imageUrl = music.Url.Replace(#"\", "").Replace("http", "https");
var task = Core.MusicHelper.GetSongPic(imageUrl, 35, 35);
var pic = task.Result;
if (pic != null)
{
MainActivity.Instance.RunOnUiThread(() =>
{
MainActivity.Instance.mImageViewSongPic.SetImageBitmap(pic);
});
}
});
}
Or pass MainActivity as a parameter to the constructor :
in your MainActivity.OnResume():
IntentFilter filter = new IntentFilter();
mReceive = new Service.Boradcast.MusicChangedBroadcastReceiver(this);
RegisterReceiver(mReceive,filter);
then in your broadcast receiver:
[BroadcastReceiver]
public class MusicChangedBroadcastReceiver: BroadcastReceiver
{
public MainActivity mMainActivity;
public MusicChangedBroadcastReceiver()
{
}
public MusicChangedBroadcastReceiver(MainActivity activity)
{
this.mMainActivity= activity;
}
public override void OnReceive(Context context, Intent intent)
{
Core.Music music = intent.GetParcelableExtra("selectedMusic") as Core.Music;
mMainActivity.mTxtSongName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Title);
mMainActivity.mTxtAuthorName.Text = Core.MusicHelper.GetTitleAndAuthor(music.Author);
System.Threading.ThreadPool.QueueUserWorkItem(o =>
{
string imageUrl = music.Url.Replace(#"\", "").Replace("http", "https");
var task = Core.MusicHelper.GetSongPic(imageUrl, 35, 35);
var pic = task.Result;
if (pic != null)
{
mMainActivity.RunOnUiThread(() =>
{
mMainActivity.mImageViewSongPic.SetImageBitmap(pic);
});
}
});
}
}
Currently in my Xamairn.Android I have 2 activities Mainactivity and SignoutActivity.
In my Mainactivity I have a button where when user clicks the button it goes to SignoutActivity.
Here I have implemented the signout codes of Auth0.
Here are the codes-
In MainAcitivity-
this.Signout.Click += delegate
{
using (var intent = new Intent(this, typeof(SignOutActivity)))
{
this.StartActivity(intent);
}
};
SignOutAcitivity-
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
this.LogoutAsync();
Finish();
}
public async Task<BrowserResult> LogoutAsync()
{
var clientOptions = new Auth0.OidcClient.Auth0ClientOptions
{
Domain ="",
ClientId = "",
Scope = "openid email offline_access",
Browser = new PlatformWebView()
};
var logoutUrl = "Signout URl";
string redirectUri = "I have proper callback uri";
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("client_id", "random1234");
dictionary.Add("returnTo", clientOptions.RedirectUri);
string endSessionUrl = new RequestUrl(logoutUrl).Create(dictionary);
var logoutRequest = new LogoutRequest();
BrowserResult browserResult = null;
browserResult = await clientOptions.Browser.InvokeAsync(new BrowserOptions(endSessionUrl, redirectUri)
{
Timeout = TimeSpan.FromSeconds((double)logoutRequest.BrowserTimeout),
DisplayMode = logoutRequest.BrowserDisplayMode
});
return browserResult;
}
Platformview-
class PlatformWebView : IBrowser
{
public Task<BrowserResult> InvokeAsync(BrowserOptions options)
{
if (string.IsNullOrWhiteSpace(options.StartUrl))
{
throw new ArgumentException("Missing StartUrl", nameof(options));
}
if (string.IsNullOrWhiteSpace(options.EndUrl))
{
throw new ArgumentException("Missing EndUrl", nameof(options));
}
var tcs = new TaskCompletionSource<BrowserResult>();
void Callback(string response)
{
ActivityMediator.Instance.ActivityMessageReceived -= Callback;
// set result
if (response == "UserCancel")
{
tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.UserCancel });
}
else
{
tcs.SetResult(new BrowserResult
{
Response = response,
ResultType = BrowserResultType.Success
});
}
}
ActivityMediator.Instance.ActivityMessageReceived += Callback;
var uri = Android.Net.Uri.Parse(options.StartUrl);
var intent = new Intent(Intent.ActionView, uri);
intent.AddFlags(ActivityFlags.NoHistory)
.AddFlags(ActivityFlags.NewTask);
Application.Context.StartActivity(intent);
return tcs.Task;
}
}
}
Problem is browser never returns to app,Also I have put a debugger at return browserResult,this debugger also does not hit.Please help me.
I am developing a simple C# Android app, which runs in Background and does a specific calculation, I have a also a widget with a TexTview in which I want to display the Calculation result.
Service.cs
Intent intent = new Intent("TEST");
intent.PutExtra("alltotale", total.ToString());
this.SendBroadcast(intent);
Then in BroadcastReceiver class, I have:
Receiver.cs
public override void OnReceive(Context context, Intent intent)
{
string nh = intent.GetStringExtra("alltotale");
Toast.MakeText(context, nh, ToastLength.Short).Show();
}
Now I want to re-use this value and display it in the widget TextView but it is not working, I am getting nothing in my Widget.
AppWidget.cs
[BroadcastReceiver(Label = "Widget1")]
[IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE" })]
[MetaData("android.appwidget.provider", Resource = "#xml/appwidgetprovider")]
public class AppWidget : AppWidgetProvider
{
Intent intent;
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
var me = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
appWidgetManager.UpdateAppWidget(me, BuildRemoteViews(context, appWidgetIds));
}
private RemoteViews BuildRemoteViews(Context context, int[] appWidgetIds)
{
var widgetView = new RemoteViews(context.PackageName, Resource.Layout.Widget);
SetTextViewText(widgetView);
RegisterClicks(context, appWidgetIds, widgetView);
return widgetView;
}
private void SetTextViewText(RemoteViews widgetView)
{
string oo = intent.GetStringExtra("alltotale");
widgetView.SetTextViewText(Resource.Id.widgetMedium, "Dabboussi");
widgetView.SetTextViewText(Resource.Id.widgetSmall, oo);
}
private static string AnnouncementClick = "AnnouncementClickTag";
private void RegisterClicks(Context context, int[] appWidgetIds, RemoteViews widgetView)
{
var intent = new Intent(context, typeof(AppWidget));
intent.SetAction(AppWidgetManager.ActionAppwidgetUpdate);
intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, appWidgetIds);
// Register click event for the Background
var piBackground = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.UpdateCurrent);
widgetView.SetOnClickPendingIntent(Resource.Id.widgetAnnouncementIcon, GetPendingSelfIntent(context, AnnouncementClick));
}
private PendingIntent GetPendingSelfIntent(Context context, string action)
{
var intent = new Intent(context, typeof(AppWidget));
intent.SetAction(action);
return PendingIntent.GetBroadcast(context, 0, intent, 0);
}
public override void OnReceive(Context context, Intent intent)
{
base.OnReceive(context, intent);
var data = intent.GetStringExtra("alltotale");
if (data != null)
{
var updateViews = new RemoteViews(context.PackageName, Resource.Layout.Widget);
SetTextViewText(updateViews);
ComponentName thisWidget = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
AppWidgetManager manager = AppWidgetManager.GetInstance(context);
manager.UpdateAppWidget(thisWidget, updateViews);
}
if (AnnouncementClick.Equals(intent.Action))
{
Toast.MakeText(context, "OPEN", ToastLength.Short).Show();
// Open another app
}
}
}
So, the value is being displayed in the Toast message in background but nothing in the widget textview. Why is that and how can I solve it ?
Edit
I have thought that maybe ISharedPreferences would do the trick, so I did the following:
Service.cs
Intent priceIntent = new Intent("com.xamarin.example.TEST");
priceIntent.PutExtra("alltotale", total.ToString());
this.SendBroadcast(priceIntent);
ISharedPreferences prSer = PreferenceManager.GetDefaultSharedPreferences(this);
ISharedPreferencesEditor prEd = prSer.Edit();
prEd.PutInt("PriceTot", Convert.ToInt32(total));
then in the AppWidget.cs file I did the following:
[BroadcastReceiver(Label = "Widget1")]
[IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE", "com.xamarin.example.TEST" })]
[MetaData("android.appwidget.provider", Resource = "#xml/appwidgetprovider")]
public class AppWidget : AppWidgetProvider
{
Intent intent;
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
var me = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
appWidgetManager.UpdateAppWidget(me, BuildRemoteViews(context, appWidgetIds));
}
private RemoteViews BuildRemoteViews(Context context, int[] appWidgetIds)
{
var widgetView = new RemoteViews(context.PackageName, Resource.Layout.Widget);
//SetTextViewText(widgetView);
RegisterClicks(context, appWidgetIds, widgetView);
return widgetView;
}
private void SetTextViewText(RemoteViews widgetView)
{
widgetView.SetTextViewText(Resource.Id.widgetMedium, "Don Dabboussi");
widgetView.SetTextViewText(Resource.Id.widgetSmall, "KK");
}
private static string AnnouncementClick = "AnnouncementClickTag";
private void RegisterClicks(Context context, int[] appWidgetIds, RemoteViews widgetView)
{
var intent = new Intent(context, typeof(AppWidget));
intent.SetAction(AppWidgetManager.ActionAppwidgetUpdate);
intent.PutExtra(AppWidgetManager.ExtraAppwidgetIds, appWidgetIds);
// Register click event for the Background
var piBackground = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.UpdateCurrent);
//widgetView.SetOnClickPendingIntent(Resource.Id.widgetAnnouncementIcon, GetPendingSelfIntent(context, AnnouncementClick));
}
private PendingIntent GetPendingSelfIntent(Context context, string action)
{
var intent = new Intent(context, typeof(AppWidget));
intent.SetAction(action);
return PendingIntent.GetBroadcast(context, 0, intent, 0);
}
public override void OnReceive(Context context, Intent intent)
{
base.OnReceive(context, intent);
ISharedPreferences prSer = PreferenceManager.GetDefaultSharedPreferences(context);
var data = prSer.GetInt("PriceTot", 0);
if (data != 0)
{
var updateViews = new RemoteViews(context.PackageName, Resource.Layout.Widget);
SetTextViewText(updateViews);
ComponentName thisWidget = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
AppWidgetManager manager = AppWidgetManager.GetInstance(context);
manager.UpdateAppWidget(thisWidget, updateViews);
}
if (AnnouncementClick.Equals(intent.Action))
{
Toast.MakeText(context, "OPEN", ToastLength.Short).Show();
// Open another app
}
}
But that didn't worked, there are no text in the textviews in my widget (no dabboussi and no kk). Why is that ?
You put a string named alltotale and you ask for a string named widgetTotale, so it is normal if it is not working. You have to change widgetTotale by alltotale
You need to get AppWidgetManager and call UpdateAppWidget() method to update the widget.
For example:
public override void OnReceive(Context context, Intent intent)
{
base.OnReceive(context, intent);
var data = intent.GetStringExtra("alltotale");
if(data != null)
{
var updateViews = new RemoteViews(context.PackageName, Resource.Layout.widget);
SetTextViewText(updateViews, intent);
// Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(context, Java.Lang.Class.FromType(typeof(MyWidget)).Name);
AppWidgetManager manager = AppWidgetManager.GetInstance(context);
manager.UpdateAppWidget(thisWidget, updateViews);
}
}
private void SetTextViewText(RemoteViews widgetView, Intent intent)
{
string oo = intent.GetStringExtra("alltotale");
widgetView.SetTextViewText(Resource.Id.widgetMedium, "Dabboussi");
widgetView.SetTextViewText(Resource.Id.widgetSmall, oo);
}
And you could refer to this official demo for more information.