I have defined a background service as follows. I have a DatabaseClass in my PCL that contains an async method InsertIntoDb. I have method StartDetect which is a listener that continuously make detection of bluetooth tags and fill up an ObservableCollection with the data detected. I want these method to continuously run in background, especially the InsertIntoDb that should continuously inserts data into the database while the app is detecting . How can I achieve this in background service in Xamarin.android ? Please help.
public class BroadcastService : Service
{
IBinder mBinder;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Toast.MakeText(this, "BroadcastService is running ", ToastLength.Long).Show();
DatabaseClass db = new DatabaseClass();
ObservableCollection<Trucks> allTrucks = new ObservableCollection<Trucks();
IDetect deObj = new Detect();
allTrucks = deObj.StartDetect();
db.InsertIntoDb(allTrucks);
base.OnStartCommand(intent, flags, startId);
return StartCommandResult.Sticky;
}
Related
I have problem with broadcast receiver in xamarin.android. Can't get it to work.
I have notification in my app working and I want to change some things in my app after I get notification (e.g. Toast message or change icon of a button) But it doesn't work. I don't know what am I doing wrong and I can't find solution because all the topics are Java related. I need something, event or broadcastreceiver to fire when user gets notification and then I want to do some stuff in my MainActivity.
So, this is the code.
BroadcastReceiver class:
[BroadcastReceiver(Enabled = true, Exported = false)]
public class MyMessageReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
bool messageReceived = intent.GetBooleanExtra("messageReceived", false);
}
}
OnMessageReceived method:
{
base.OnMessageReceived(message);
SendNotification(message.GetNotification().Body);
LocalBroadcastManager broadcaster = LocalBroadcastManager.GetInstance(this);
Intent intent = new Intent("message");
intent.PutExtra("messageReceived", true);
broadcaster.SendBroadcast(intent);
}
And OnResume and OnPause methods:
protected override void OnResume()
{
base.OnResume();
LocalBroadcastManager.GetInstance(this).RegisterReceiver(myReceiver, new IntentFilter("message"));
RegisterReceiver(myReceiver, new IntentFilter("message"));
}
protected override void OnPause()
{
base.OnPause();
LocalBroadcastManager.GetInstance(this).UnregisterReceiver(myReceiver);
}
I don't know how to receive that info for example in my OnCreate method in MainActivity? I tried with
messageReceived = Intent.GetBooleanExtra("messageReceived", false);
if (messageReceived)
{
Toast.MakeText(this, "new notification", ToastLength.Long).Show();
}
But that doesn't work, messageReceived is null.
I know it is a bit too late but better late than never :
After analysing the firebase messaging I have done a suitable workaround for this purpose :
When your application is in the background the handle intent method is called by default on receiving push notification :
public override void HandleIntent(Intent p0)
{
base.HandleIntent(intent);
//Your code to know that you received a notification (backgrounnd)
// Use shared preference for this
}
Don't know how to use shared preferences check this.
For more information on how handle intent works check my answer out here.
When the application is in the foreground you can simply use on message received method as such :
public override void OnMessageReceived(Context context, Intent intent)
{
//Your code to know that you received a notification (backgrounnd)
// Use shared preference for this
}
Then, wherever you need to use this you can get a flag or count or whatever using shared preferences.
In case of any queries revert!
I have implemented a background service. When I boot my device, the background service is started and toast message is displayed. I want a toast message to appear each 5 seconds while the service in running. The following code does not seem to be doing the job:
[Service]
public class BroadcastService : Service
{
IBinder mBinder;
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Toast.MakeText(this, "BroadcastService Started...", ToastLength.Long).Show();
DoWork();
base.OnStartCommand(intent, flags, startId);
return StartCommandResult.Sticky;
}
public void DoWork()
{
while (true)
{
Toast.MakeText(this, "BroadcastService is running at each 5 seconds...", ToastLength.Long).Show();
Thread.Sleep(5000);
}
}
Can somebody please advise what is wrong above and help to achieve this in Xamarin.android ?
I want a toast message to appear each 5 seconds while the service in running. The following code does not seem to be doing the job
Once OnStartCommand finish executing, DoWork won't execute any more.
According to your requirement, you need to use JobScheduler together with JobInfo to create a periodic task. For how to use JobScheduler, You can refer to the official demo of JobScheduler
I've been searching for a way to send a local message within my app and found a tutorial from the Xamarin website on Broadcast Receivers here, more specifically at the bottom of the web page concerning LocalBroadcastManager. I followed the tutorial and read the page a few times but my BroadcastReceiver class still isn't receiving anything when I send a message. I've hit a lot of the questions concerning LocalBroadcastManager for java, but can't seem to figure out what's missing for C#.
This is the code that's triggering a sent message:
Intent intent = new Intent("dirty");
intent.PutExtra("dirtyAppCount", dirtyAppCount);
LocalBroadcastManager.GetInstance(Context).SendBroadcast(intent);
Here's where I'm registering my receiver in OnResume():
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Unregistering receiver in OnPause():
UnregisterReceiver(_dirtyMessageReceiver);
And here's my receiver class:
[BroadcastReceiver(Enabled = true, Exported = false)]
public class DirtyBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
int dirtyAppCount = intent.GetIntExtra("dirtyAppCount", 0);
OnMessageReceived?.Invoke(this, new MessageArgs(dirtyAppCount));
}
}
There are two issues with this code. First, you should use be registering the Receiver with the LocalBroadcastManager:
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Should be
_dirtyMessageReceiver = new DirtyBroadcastReceiver();
LocalBroadcastManager.GetInstance(this).RegisterReceiver(_dirtyMessageReceiver, new IntentFilter("dirty"));
Secondly, the Unregistering of the Receiver should be one against the LocalBroadcastManager as well:
UnregisterReceiver(_dirtyMessageReceiver);
becomes
LocalBroadcastManager.GetInstance(this).UnregisterReceiver(_dirtyMessageReceiver);
You need to add a broadcast receiver for these.For example, Set Android.Content.Intent to ActionTimeTick so that android os will broadcast message(an android intent) whenever time is changed.
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionTimeTick })]
public class GridStartBroadcastReceiver : BroadcastReceiver
{
public static readonly string GRID_STARTED = "GRID_STARTED";
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == GRID_STARTED)
{
//your logic
}
}
}
you need to register the broadcast receiver first. Add these code to oncreate method to register broadcast receiver.
IntentFilter filter = new IntentFilter(GridStartBroadcastReceiver.GRID_STARTED);
filter.AddCategory(Intent.CategoryDefault);
_receiver = new GridStartBroadcastReceiver();
RegisterReceiver(_receiver, filter);
Next send the broadcast to the broadcast receiver.
//calling
Intent BroadcastIntent = new Intent(this, typeof(MainActivity.GridStartBroadcastReceiver));
BroadcastIntent.SetAction(MainActivity.GridStartBroadcastReceiver.GRID_STARTED);
BroadcastIntent.AddCategory(Intent.CategoryDefault);
SendBroadcast(BroadcastIntent);
In Visual Studio I created a new class library (Xamarin Forms) :-
Xamarin class library
Here I added my service and gave it the most basic implementation possible for a started service (note - not a bound service. Expecting - toasts to be displayed when the application is started / stopped :-
namespace AndroidBatteryService
{
public class AndroidBatteryService : Service
{
public AndroidBatteryService()
{
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Toast.MakeText(this, "The Battery Service was just started", ToastLength.Long).Show();
return base.OnStartCommand(intent, flags, startId);
}
public override void OnCreate()
{
base.OnCreate();
}
public override void OnDestroy()
{
base.OnDestroy();
Toast.MakeText(this, "The Battery Service has been stopped", ToastLength.Long).Show();
}
public override IBinder OnBind(Intent intent)
{
//started service, NOT a binded service - return null...
return null;
}
}
}
In another project I am invoking this service my running the following code :-
public void StartBatteryService()
{
Intent intent = new Intent(Android.App.Application.Context, typeof(AndroidBatteryService.AndroidBatteryService));
Android.App.Application.Context.StartService(intent);
}
The code runs (I can step over it), but the OnStartCommand method in the actual service is not run and I am expecting it to. Any ideas??
I think the problem is that you need to decorate the service class with:-
[Service (Label = "AndroidBatteryService", Icon = "#drawable/Icon") ]
This causes Xamarin to put the following into the generated AndroidManifest.xml file during the build (you can find this in the \obj\Debug\android directory)
<service android:icon="#drawable/icon" android:label="AndroidBatteryService" android:name="md55...1a.AndroidBatteryService" />
I used a very similar piece of code in my app and it worked fine. (Although you've probably worked this out by now.)
I have a strange problem. I'm using an android app as server and a WinForms application as client. They are both communicating over a TCP socket connection. I have following piece code in my App:
public class StateListener : PhoneStateListener
{
private readonly MainActivity _activity;
public StateListener(MainActivity activity)
{
_activity = activity;
}
public override void OnCallStateChanged(CallState state, string number)
{
base.OnCallStateChanged(state, number);
_activity.UpdateCallState(state, number);
}
}
private void UpdateCallState(CallState state, string number)
{
PhoneState = state.ToString();
}
And in a thread called from the MainActivity:
while (PhoneState == "Idle") { }
//some code
Now the WinfForms application is making calls over the phone with AT Commands.
When I trying to make a call directly over the phone (before the connection is established) the state listener works. When I'm doing this over AT commands within the application then the state does not change at all.
Could this be because of the while loop which blocks the method to be called or could this come from the AT command?
Thank you!