Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

My service is canceled when I close my application

I want to create an application that obtains the GPS coordinates and sends them to a WebService at every moment, but when closing the apication completely stops sending to the WebService, how do I stop the service? What am I doing wrong?
I have this following code in my Main Acivity

`using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Locations;
using Android.Support.V7.App;
using Android.Content;
using FuncionesAndroid.Servicios;
using System.Threading.Tasks;
using ZXing.Mobile;
using ZXing.Net.Mobile.Forms;

namespace FuncionesAndroid.Droid
{
[Activity(Label = "FuncionesAndroid", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : AppCompatActivity /*, ILocationListener*/
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.main_android);
StartService(new Android.Content.Intent(this,typeof(BackgroundGps)));
}
}`

This is the service

`using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;

namespace FuncionesAndroid.Droid
{
[Service]
class BackgroundGps : Service
{
private Servicios.Gps _gps;
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}

    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        //return base.OnStartCommand(intent, flags, startId);
        _gps = new Servicios.Gps();
        //return StartCommandResult.NotSticky;
        return StartCommandResult.Sticky;
    }

    public override bool StopService(Intent name)
    {
        Log.Info("this","StopService");
        return base.StopService(name);
    }
}

}`

Where do I get the coordinates

`using System;
using System.Collections.Generic;
using System.Text;
using FuncionesAndroid.Model;
using Plugin.Geolocator;
using Plugin.Geolocator.Abstractions;
using Xamarin.Forms;

namespace FuncionesAndroid.Servicios
{
public class Gps : ContentPage
{
private MensajeRespuesta _mensaje;
private string _lat;
private string _lon;
private string _alt;
public Gps()
{
InitializePlugin();
}

    private async void InitializePlugin()
    {
        if(!CrossGeolocator.IsSupported)
        {
            DisplayAlert("Error", "Ha ocurrido un error al cargar el plugin","Ok");
            return;
        }

        if(!CrossGeolocator.Current.IsGeolocationEnabled || !CrossGeolocator.Current.IsGeolocationAvailable)
        {
            DisplayAlert("Advertencia", "Revise la configuracion GPS de su dispositivo", "Ok");
            return;
        }
        var listen = await CrossGeolocator.Current.StartListeningAsync(new TimeSpan(0,0,5),0);
        CrossGeolocator.Current.PositionChanged += Current_PositionChanged;
    }

    private async void Current_PositionChanged(object sender, PositionEventArgs e)
    {
        if(!CrossGeolocator.Current.IsListening)
        {
            return;
        }

        var position = CrossGeolocator.Current.GetPositionAsync();
        _lat = position.Result.Latitude.ToString();
        _lon = position.Result.Longitude.ToString();
        _alt = position.Result.Altitude.ToString();

        _mensaje = await Servicios.Servicio.mandarCoordenadas(1,_lat,_lon,_alt);
    }
}

}`

Where I send the data to the WebService

` using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Http;
using Newtonsoft.Json;
using FuncionesAndroid.Model;
using System.Threading.Tasks;

namespace FuncionesAndroid.Servicios
{
public class Servicio
{
readonly static string url_base = "192.168.7.244:92";
public async static Task mandarImagen(String base64)
{
try
{
var url = url_base + string.Format("/imagenXamarin");
var client = new HttpClient();
MultipartFormDataContent content = new MultipartFormDataContent();
//content.Add(new StringContent(base64), "strBaseImagen");
content.Add(new StringContent(base64), "strBaseImagen");
client.Timeout = TimeSpan.FromSeconds(60);
client.BaseAddress = new Uri(url);
var response = await client.PostAsync(client.BaseAddress, content);
//var response = await client.GetAsync(client.BaseAddress);
response.EnsureSuccessStatusCode();
var jsonResult = response.Content.ReadAsStringAsync().Result;
var respuesta = JsonConvert.DeserializeObject(jsonResult);
return respuesta;
}catch(Exception e)
{
var respuesta = new MensajeRespuesta();
respuesta.status = "ERROR_SERVER";
return respuesta;
}
}

    public async static Task<MensajeRespuesta> mandarCoordenadas(int idUser,String lat,String lon, String alt)
    {
        try
        {
            var url = url_base + string.Format("/setCoordenadas");
            var client = new HttpClient();
            MultipartFormDataContent content = new MultipartFormDataContent();
            content.Add(new StringContent(idUser.ToString()),"idUser");
            content.Add(new StringContent(lat), "strLat");
            content.Add(new StringContent(lon), "strLon");
            content.Add(new StringContent(alt), "strAlt");
            client.Timeout = TimeSpan.FromSeconds(60);
            client.BaseAddress = new Uri(url);
            var response = await client.PostAsync(client.BaseAddress, content);
            response.EnsureSuccessStatusCode();
            var jsonResult = response.Content.ReadAsStringAsync().Result;
            var respuesta = JsonConvert.DeserializeObject<MensajeRespuesta>(jsonResult);
            return respuesta;
        }
        catch (Exception e)
        {
            var respuesta = new MensajeRespuesta();
            respuesta.status = "ERROR_SERVER";
            return respuesta;
        }
    }
}

}
`

Best Answers

  • jezhjezh Member, Xamarin Team Xamurai
    Accepted Answer

    @Celtarius
    In Android, starting in Android 8.0 (API level 26), an Android application no longer have the ability to run freely in the background. For more details about this, you can refer to Background Execution Limits in Android 8.0:

    But you can try to restarted the service once it been finished by a BroadcastReceiver .
    The function of BroadcastReceiver is to receive a signal when someone or something kills the service; its role is to restart the service.

    For more details, you can check:
    https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
    Though it's Java code, it's easy to understand and convert

  • CeltariusCeltarius Member ✭✭
    edited May 2019 Accepted Answer

    @jezh

    Thank you very much Jezh, those links that you passed me helped me to guide me, only that it is bad in 2 lines of code instead of one:
    startService(mServiceIntent);
    It must have been:
    StartForegroundService(servicioIntent);
    and within the method StartForeground use StartForeground ()

Answers

  • CeltariusCeltarius Member ✭✭

    I'm sorry for my code format, I know it looks bad, I still do not know how to fit it well

  • jezhjezh Member, Xamarin Team Xamurai
    Accepted Answer

    @Celtarius
    In Android, starting in Android 8.0 (API level 26), an Android application no longer have the ability to run freely in the background. For more details about this, you can refer to Background Execution Limits in Android 8.0:

    But you can try to restarted the service once it been finished by a BroadcastReceiver .
    The function of BroadcastReceiver is to receive a signal when someone or something kills the service; its role is to restart the service.

    For more details, you can check:
    https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
    Though it's Java code, it's easy to understand and convert

  • CeltariusCeltarius Member ✭✭

    @jezh
    I'm already doing the example, but the only thing I do not know how to translate is the double point in the for a C # Xamarin

    private boolean isMyServiceRunning(Class<?> serviceClass) { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (serviceClass.getName().equals(service.service.getClassName())) { Log.i ("isMyServiceRunning?", true+""); return true; } } Log.i ("isMyServiceRunning?", false+""); return false; }

  • CeltariusCeltarius Member ✭✭

    I already saw that it translates as
    foreach(ActivityManager.RunningServiceInfo service in manager.GetRunningServices(Integer.MaxValue))
    In a moment I commented to them how it was with the code ...

  • jezhjezh Member, Xamarin Team Xamurai

    @Celtarius
    You can check:

     private bool IsServiceRunning(Type serviceClass)
         {
            ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);
            IList<ActivityManager.RunningServiceInfo> list = manager.GetRunningServices(maxNum: int.MaxValue);
            for (int i = 0; i < list.Count; i++)
            {
                if (serviceClass.FullName.Equals(list[i].Service.ClassName))
                {
                    return true;
                }
            }
            return false;
         }
    
  • CeltariusCeltarius Member ✭✭
    edited May 2019 Accepted Answer

    @jezh

    Thank you very much Jezh, those links that you passed me helped me to guide me, only that it is bad in 2 lines of code instead of one:
    startService(mServiceIntent);
    It must have been:
    StartForegroundService(servicioIntent);
    and within the method StartForeground use StartForeground ()

Sign In or Register to comment.