Reputation: 1009
I'm developing an Android application with Xamarin Forms that is composed of an interface and also a background service. I need that the service works also when the interface application is closed. If I add "IsolatedProcess = true" into the service the graphical interface still works but the service crashes. I read a lot of posts with possible solutions but they don't work. (I tried to compile in release mode and also to remove "Use Shared Runtime" flag).
I'm compiling with Android 8.1 (Oreo) as Target Framework. The target environment is Android 4.2.
I start the service into OnCreate method of the MainActivity class:
Intent testIntent = new Intent(this.BaseContext, typeof(TestService));
StartService(testIntent);
The service class:
[Service(IsolatedProcess = true, Exported = true, Label = "TestService")]
public class TestService : Service
{
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
Device.StartTimer(new TimeSpan(0, 0, 40), () =>
{
//Code executed every 40 seconds
});
base.OnStartCommand(intent, flags, startId);
return StartCommandResult.Sticky;
}
public override bool StopService(Intent name)
{
return base.StopService(name);
}
}
If I remove "IsolatedProcess = true" the service works but it will be stopped when I will close the application interface process.
Upvotes: 3
Views: 402
Reputation: 1009
I solved the issue by changing the value of the attribute IsolatedProcess to true, removing the Device.StartTimer instruction and by introducing a BroadcastReceiver.
MainActivity class:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static Intent testServiceIntent;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
testServiceIntent = new Intent(this.BaseContext, typeof(TestService));
LoadApplication(new App());
}
}
The service class:
[Service(IsolatedProcess = false, Exported = true, Label = "TestService")]
public class TestService : Service
{
System.Threading.Timer _timer;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
businessLogicMethod();
base.OnStartCommand(intent, flags, startId);
return StartCommandResult.Sticky;
}
public void businessLogicMethod()
{
//My business logic in a System.Threading.Timer
}
}
The Broadcast Receiver class:
[BroadcastReceiver]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class TestApplicationBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Log.Info("TestApp", "******* Loading Application *******");
try
{
if (intent.Action.Equals(Intent.ActionBootCompleted))
{
Intent service = new Intent(context, typeof(TestService));
service.AddFlags(ActivityFlags.NewTask);
context.StartService(service);
}
}
catch (Exception ex)
{
Log.Error("TestApp", "******* Error message *******: " + ex.Message);
}
}
}
I hope that can be useful for someone.
Upvotes: 2