1

I am running a telemetry service in my app. This service is checking for changes in WiFi environment once a second and if changes are detected it notifies a remote db. I need this service to continue running even if the app is swiped from recent apps or closed.

I followed Continue Service even if application is cleared from Recent app and it seems to work on many devices except for Xiaomi. I've tried many things advised for this device:

  1. enable auto-start.
  2. disable battery optimization for that app.
  3. Tried using a broadcast receiver to start the service
  4. Tried using timer thread and scheduleExecutorservice instead of runnable. didn't make a difference.

This is my latest sample code :

package com.example.csi1;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;

public class MainService extends Service {
    public Context context = this;
    public Handler handler = null;
    public static Runnable runnable = null;
    public static int count = 0;
    public int restart = 0;
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        Toast.makeText(this, "MainService onStartCommand", Toast.LENGTH_LONG).show();
        Bundle extras = intent.getExtras();
        count = 0;

        handler = new Handler();
        runnable = new Runnable(){
            public void run() {
                count = count+1;

                WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo;

                wifiInfo = wifiManager.getConnectionInfo();
                if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) {
                    String ssid = wifiInfo.getSSID();
                    Log.i("Service", "SSID:"+ssid);
                    Toast toast = Toast.makeText(context, "Service iter " + String.valueOf(count)+ " " + ssid, Toast.LENGTH_LONG );
                    toast.setGravity(Gravity.TOP|Gravity.RIGHT, 0, 0);
                    toast.show();
                }

                handler.postDelayed(runnable, 1000);

            }
        };

        handler.postDelayed(runnable, 3000);
        return START_STICKY;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Toast.makeText(this, "onTaskRemoved", Toast.LENGTH_LONG).show();
        if (restart == 0) {
            PendingIntent service = PendingIntent.getService(
                    getApplicationContext(),
                    1001,
                    new Intent(getApplicationContext(), MainService.class),
                    PendingIntent.FLAG_ONE_SHOT);

            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
            restart=1;
            Toast.makeText(this, "Service restarted", Toast.LENGTH_LONG).show();
        }
    }
    @Override
    public void onDestroy(){
        Toast.makeText(this, "onDestroy", Toast.LENGTH_SHORT).show();
        if (restart == 0) {
            PendingIntent service = PendingIntent.getService(
                    getApplicationContext(),
                    1001,
                    new Intent(getApplicationContext(), MainService.class),
                    PendingIntent.FLAG_ONE_SHOT);

            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
            restart=1;
            Toast.makeText(this, "Service restarted", Toast.LENGTH_LONG).show();
        }
        super.onDestroy();
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

it runs fine on Samsung device and google nexus emulator, but whenever i run it on Red mi and swipe the app from recent apps,app dies and service with it. Is there a solution for Red mi devices or this is some well known limitation ?

ncormac
  • 11
  • 3

1 Answers1

0

Xiaomi's MIUI and a couple of others are very aggressive on removing background services. As a user you are able to disable it following these steps (for xiaomi). But I am not aware of a solution to circumvent it as a developer.

So you're not doing anything wrong, some phones just don't like background services taking battery life. Similar discussion can be found here: "Protected Apps" setting on Huawei phones, and how to handle it. Their solution is basically having the user disable it by calling the optimization manager for each of the problematic devices

Software Person
  • 2,526
  • 13
  • 18
  • Thank you Software person. I've done these steps but the service still gets killed, so i understand that the os will simply not let me restart it ? – ncormac Jul 01 '19 at 08:08
  • In general yes, but maybe check out this: https://stackoverflow.com/a/35220476/11702000. And see if that helps. – Software Person Jul 01 '19 at 08:34