Unkillable Service in Android

You need to make sure that my Service is not killed by the system and other garbage cleaners.

The code itself:

Manifest.xml

<service
        android:name=".NotificationService"
        android:enabled="true"
        android:exported="true"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETE"
        android:process=":BatMonitoring">
    </service>

    <receiver
        android:name=".BootReceiver"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
        android:enabled="true">

        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            <action android:name="android.intent.action.REBOOT"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

    </receiver>

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    intentService = new Intent(this,NotificationService.class);
    startService(intentService);
}

BootReceiver.java

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
            Intent serviceIntent = new Intent(context, NotificationService.class);
            context.startService(serviceIntent);
    }
}

NotificationService.java

public class NotificationService extends Service {

    private NotificationManager notificationManager;
    public static final int DEFAULT_NOTIFICATION_ID = 101;

    @Override
    public void onCreate() {
        super.onCreate();
        notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
        this.registerReceiver(this.mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));


    }


    public int onStartCommand(Intent intent, int flags, int startId) {

        return START_STICKY;

    }
    BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int chargeState = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);

            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                    status == BatteryManager.BATTERY_STATUS_FULL;

            switch (chargeState) {
                case BatteryManager.BATTERY_STATUS_CHARGING:

                    if (isCharging) {

                        NotificationCompat.Builder builder = new NotificationCompat.Builder(NotificationService.this)
                                .setContentTitle("Charging...")
                                .setContentText("Battery level is: " + Integer.toString(level))
                                .setSmallIcon(android.R.drawable.stat_notify_chat);

                        Notification notification = builder.build();
                        notification.defaults |= Notification.DEFAULT_VIBRATE;
                        notification.defaults |= Notification.DEFAULT_SOUND;

                        startForeground(DEFAULT_NOTIFICATION_ID, notification);

                    }
                    break;

                case BatteryManager.BATTERY_STATUS_FULL:

                    break;
                case BatteryManager.BATTERY_STATUS_DISCHARGING:

                    break;
            }

        }
    };


   @Override
    public void onDestroy () {
        super.onDestroy();

        notificationManager.cancel(DEFAULT_NOTIFICATION_ID);
        this.unregisterReceiver(this.mBatteryInfoReceiver);

        //Disabling service
        stopSelf();
    }


    public IBinder onBind(Intent intent) {
        return null;
    }
}

I took this question as one of the examples ,but it still doesn't work as it should.

I will be very grateful for any help!

UPD: Finally, the question was not solved, but if anyone needs it, then adding a restart of the service in void onDestroy () and in onTaskRemoved(Intent rootIntent) partially helped.

Author: Дух сообщества, 2016-10-27

1 answers

I have also been looking for an official way to make such a service for a long time.

I tried to make startForeground() for a service running in a separate process and it worked. At least the process remains alive and the notification is displayed. But this is for those services that can be displayed to the user.

The second option is when the user does not need to display anything. Look at the quote:

Binding to a running service.

As described in the Services article, you can create a service, which is both running and bound at the same time. This means that the service can be started by calling the startService () method, which allows the service to run indefinitely, and also allows clients to bind to it by calling the bindService () method.

If you allow the service to start and bind, then after it starts , the system does not destroy it after canceling all client bindings. Instead , you must explicitly stop the service by calling the stopSelf() method or stopService(). Although you usually need to implement either the onBind () method or the onStartCommand () method, in some cases you need to implement both of these methods. For example, in a music player, it may be useful to allow the service to run for an unlimited time, and also ensure that it is bound. This way, the operation can start the service to play music that will play even after the user exits the app. After the user returns to the application, the operation can undo the binding to the service to regain playback control.

Https://developer.android.com/guide/components/bound-services.html#Lifecycle

 1
Author: Michael Gaev, 2020-06-12 12:52:24