Starting an android Service from Xamarin forms - c#

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.)

Related

FCM and xamarin.android - broadcast receiver doesn't work

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!

Invoke a method continuously in background service without blocking the app xamarin

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;
}

Show a toast message after each five seconds in Background Service in Xamarin.android

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

Stop service without error "Service cannot be started. The handle is invalid"

I have WIndows Service app and want to stop service when main code is executed. I am trying to execute ServiceBase.Stop() in OnStart event, everything works fine, the service is stopped but I get annoying error message in event viewer
"Service cannot be started. The handle is invalid"
Any ideas how to stop windows service without errors?
public partial class VirtualServerInitService : ServiceBase
{
public ILogger EventLogger = new EventLogger();
public VirtualServerInitService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLogger.Write("Starting service!");
new VirtualServerInit(EventLogger).Run();
EventLogger.Write("VirtualServerInit code was executed");
Stop();//This code works and also gives error in event viewer
}
protected override void OnStop()
{
EventLogger.Write("Stopping service!");
}
}
Use a thread to make sure the OnStart method finishes. The threadpool will put your workitem on the queue and once a thread it is available it will execute your Run method and then calls Stop on the service. By then the windows service manager already handled the succesful start of your service and hence no error will be sent to the Eventlog when Stop is called.
protected override void OnStart(string[] args)
{
EventLogger.Write("Starting service!");
ThreadPool.QueueUserWorkItem( _ => {
new VirtualServerInit(EventLogger).Run();
EventLogger.Write("VirtualServerInit code was executed");
this.Stop();
});
}
You might consider leaving the service running and use a CustomCommand to control if actual work needs to be done. For that you can override OnCustomCommand and send a pre determined integer to ask the service to perform a particular task for example by calling sc virtualsvc control 128 from the commandline.
protected virtual void OnCustomCommand(int command)
{
switch(command)
{
case 128:
new VirtualServerInit(EventLogger).Run();
EventLogger.Write("VirtualServerInit code was executed");
// maybe keep state if this only can be run once
break;
default:
EventLogger.Write(String.Format("Unknown control code:{0}", command));
break;
}
}

Remote notification (GCM) into Xamarin.Android (monodroid) when app exit

I followed this tutorial
The main problem is :
What is WAKELOCK_KEY in their code ? What I must put here ?
What is classType in their code ? What I must put here ?
For the WAKELOCK_KEY I just put "NOTIF", and for classType is use typeof(MyIntentService).
I receive notification but can't receive notification when I kill the application. So how to manage this in Xamarin (no PushSharp or similar lib) ?
(My code is the same as in the tutorial, except for WAKELOCK_KEY and classType).
If you follow the tutorial, you just have to do that (seems my solution for the wakelock_key and the classType was good)
:-)
[BroadcastReceiver]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
MyIntentService.RunIntentInService(context, intent);
}
}

Categories

Resources