The best approach to running a service on Android

I have a service that has a variable lifespan. It can be performed from 5 minutes to 2 hours (for example). Therefore, I am looking for the best approach to this, and my service should provide the following features:

  • Send (to my server) lat-long every 5 seconds and some additional information ( string 's, boolean and int ' s)

I tried the "normal" service and tried to do something similar for this:

 public class MyFiveSecondsService extends Service { private Handler handler; Runnable r = new Runnable() { @Override public void run() { //here send my new data } }; public void onCreate(){ super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if(handler == null){ handler = new Handler(); } handler.post(r); return super.onStartCommand(intent, flags, startId); } } 

This code actually works, but I am having some performance issues with this approach, so I tried to do something like this:

 public class SendUniquePositionIntentService extends IntentService { public SendUniquePositionIntentService() { super("co.bomboapp.Service.IntentService.SendUniquePositionIntentService"); } @Override public void onCreate() { super.onCreate(); } @Override protected void onHandleIntent(Intent intent) { //do the logic here } } public class MyFiveSecondsService extends Service { private Handler handler; Runnable r = new Runnable() { @Override public void run() { //call my SendUniquePositionIntentService here } }; public void onCreate(){ super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if(handler == null){ handler = new Handler(); } handler.post(r); return super.onStartCommand(intent, flags, startId); } } 

And this approach did not work when I closed the application, all services continued to work. Therefore, before starting any other attempt to achieve this, I need some direction, what is the best approach for this “endless maintenance cycle” and maintain performance?

I am using Android 4.1 as a min API and targeting a 5.0 API . My test device is Nexus 5 running Android 6. Now I use parse.com as a database.

+5
source share
1 answer

"I tried the" normal "service ... but I had some performance issues"

By default, the service starts in the main thread of the application, so when you create a handler with

 public int onStartCommand(Intent intent, int flags, int startId) { if(handler == null){ handler = new Handler(); } ... } 

the handler is associated with the main Looper thread, and all messages and runnables are delivered and then executed in the thread. This is the cause of "performance issues." From the doc:

Remember that if you use the service, it still works in the main thread of your application by default ...

Regarding the second approach and part

"... when I closed the application, all services continued to work

you didn’t mention exactly how you "close" the application, but I see

 public int onStartCommand(Intent intent, int flags, int startId) { ... return super.onStartCommand(intent, flags, startId); } 

which means that if the system kills the service, it will be recreated by default. Therefore, if "closing" your application means killing it, the following chain of actions occurs:

  • The system recreates MyFiveSecondsService ,
  • onStartCommand() is called and the handler sends runnable
  • as part of the run() SendUniquePositionIntentService launched

From the onStartCommand() documentation:

the default implementation calls onStart (Intent, int) and returns START_STICKY or START_STICKY_COMPATIBILITY.

Please note that starting a service from another (for example, starting SendUniquePositionIntentService from MyFiveSecondsService in your case) is redundant if you did not intend to.

The last part of your question is confusing to me. On the one hand, this will not work for you, because "... any service continued to work," but on the other hand, you would like to "make it an" endless loop service "" ...?

If you need to send information such as "strings, booleans and ints" to the server (without feedback from the component that started the service), I suppose it's simple enough that you can use IntentService . This is an out-of-the-box framework that does its job in the background thread (avoiding freezing the main thread) and stops after that. As an example, you can use the documentation for IntentService - it is well written.

Also note that the behavior of a service after it is killed by the system depends on the flag returned by onStartCommand() . For instance. use START_NOT_STICKY to not recreate the service after killing the application, or START_REDELIVER_INTENT to recreate it with the last Intent repeatedly.

+3
source

Source: https://habr.com/ru/post/1235263/


All Articles