После закрытия приложения перестает работать Service

Я создал сервис и он отлично отрабатывает как при запущенном так и при выключенном приложении. Но потом я узнал что он блокирует activity, так как отрабатывает в основном потоке. После запуска его в новом потоке он перестал работать после закрытия приложения. Вот код моего сервиса:

public class InetConnectionService extends Service {
final String channelId = "CHANNEL_ID";
final int id = 1;
NotificationManager notificationManager;
Intent intent;
PendingIntent pendingIntent;

public InetConnectionService() {
}

@Override
public void onCreate() {
    super.onCreate();
    notificationManager =
            (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    intent = new Intent(getApplicationContext(), MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                if (hasConnection(getApplicationContext())) {
                    NotificationCompat.Builder notificationBuilder =
                            new NotificationCompat.Builder(getApplicationContext(), channelId)
                                    .setAutoCancel(false)
                                    .setSmallIcon(R.mipmap.ic_launcher)
                                    .setWhen(System.currentTimeMillis())
                                    .setContentIntent(pendingIntent)
                                    .setContentTitle("title")
                                    .setContentText("text")
                                    .setPriority(PRIORITY_HIGH);
                    createChannelIfNeeded(notificationManager);
                    notificationManager.notify(id, notificationBuilder.build());
                    break;
                }
            }
            stopSelf();
        }
    }).start();
    super.onStartCommand(intent, flags, startId);
    return Service.START_STICKY;
}

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

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
}

public boolean hasConnection(final Context context) {//проверяет подключение к интернету
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    networkInfo = cm.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}

public void createChannelIfNeeded(NotificationManager manager) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_DEFAULT);
        manager.createNotificationChannel(channel);
    }
}

Ответы (1 шт):

Автор решения: Olmicron
  1. Сервис может работать в том же потоке что и активность - и это в большинстве случаев лучший вариант, особенно если нужен доступ к данным в/из активности. Если запустить в фоне - придётся делать свой транспорт. Но в любом случае сервис остановится при завершении активности (об этом далее).
  2. Сервис не зависит от работы активности. Есть только одно большое НО. Сервис не может работать (при отсутствии активности) в фоне, без вывода уведомления. Т.е. если активность закрыта, у вас есть 5-10 секунд, чтобы показать пользователю уведомление о работающем сервисе. И такое уведомление будет висеть постоянно, пока работает сервис. Т.к. "пользователь должен знать, что в фоне работает сервис".
  3. Есть возможность запросить работу в фоне у пользователя и попробовать запускать сервис без уведомления - но эта штука не везде работает и надеяться не стоит. А если и сработает - то уведомление всё равно будет показано, но уже в качестве оповещения системы о работающем приложении в фоне.
  4. Системные приложения могут использовать сервисы никак не уведомляя пользователя об этом. Но это уже другой случай...

Собственно для привязки сервиса к уведомлению нужно сделать примерно следующее:

/**
 * Набросал быстро код, он может да же и не работать, но смысл будет понятен
 */
NotificationManager notificationManager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);

Intent notificationIntent = new Intent(service, MainActivity.class);
// Тут устанавливаем флаги в интент, добавляем какие нужно данные  и т.п.

PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notificationBuilder = new Notification.Builder(service);
notificationBuilder.setSmallIcon(R.drawable.status_bar_icon);
notificationBuilder.setContentIntent(pendingIntent);
// Далее тут ещё нужно настроить вид уведомления (ну там текст, картинки и т.п.)

// Теперь показываем пользователю уведомление привязанное к сервису:
service.startForeground(NOTIFICATION_ID, notificationBuilder.build());

// После всего этого сервис будет спокойно работать в не зависимости от активности
→ Ссылка