Время от времени происходит сбой фоновой службы

Когда мое приложение находится в состоянии ожидания, то есть никто не использует приложение или оно закрыто, но фоновая служба работает непрерывно. У меня проблема с тем, что фоновая служба в моем приложении дает сбой. Это случилось всего два раза. Это не происходит на регулярной основе. У меня нет трассировки стека в Crashlytics, а есть только отчет о сбое, показывающий, что приложение дает сбой в Runnable интерфейсной функции run() (скриншот прилагается)

введите здесь описание изображения

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = getApplicationContext();

        handler = new Handler();
        handler.removeCallbacks(restartThread);
        handler.post(restartThread);
        return START_STICKY;
    }

    private Runnable restartThread = new Runnable() {
        @Override
        public void run() {
            handler.postDelayed(restartThread, NOTIFY_INTERVAL);
        }
    };

Возможно ли, что ОС убивает фоновую службу из-за нехватки памяти?


person Waqas Ahmed    schedule 27.05.2018    source источник


Ответы (2)


Это просто предложение, а не решение вашей проблемы

Возможно, лучше использовать JobService вместо использования фоновой службы. У них так много ограничений на фоновые службы от Android Oreo и выше.

person Pavan Varma    schedule 27.05.2018
comment
Кстати, см. мой ответ выше. Рекомендуемый подход от Google — использовать WorkManager. Это обертка JobService и работает на любом уровне API. - person Shmuel; 28.05.2018

Очень вероятно, что есть множество проблем с этой реализацией. Фоновые службы заблокированы в современных версиях Android, и даже в более старых версиях запуск такой службы (с циклом Runnable) очень подвержен ошибкам.

По состоянию на 2018 год лучшим способом запуска запланированной задачи является использование библиотеки WorkManager из компонентов архитектуры Android.

WorkManager выбирает подходящий способ планирования фоновой задачи — в зависимости от уровня API устройства и включенных зависимостей WorkManager может использовать JobScheduler, Firebase JobDispatcher или AlarmManager. Вам не нужно писать логику устройства, чтобы выяснить, какие возможности есть у устройства, и выбрать подходящий API; вместо этого вы можете просто передать свою задачу WorkManager и позволить ему выбрать наилучший вариант.

https://developer.android.com/topic/libraries/architecture/workmanager

Вы можете определить такую ​​​​задачу

public class CustomWorker extends Worker {
  ...
}

а затем запланировать это так

new PeriodicWorkRequest.Builder photoWorkBuilder =
        new PeriodicWorkRequest.Builder(CustomWorker.class, 12,
                TimeUnit.HOURS);
// ...if you want, you can apply constraints to the builder here...

// Create the actual work object:
PeriodicWorkRequest work = customWorkerBuilder.build();
// Then enqueue the recurring task:
WorkManager.getInstance().enqueue(work);
person Shmuel    schedule 27.05.2018
comment
Большое спасибо @Shmuel за ваше предложение. С помощью этого диспетчера работ я могу запускать код внутри метода run() каждую секунду, определяя его как задачу? - person Waqas Ahmed; 27.05.2018
comment
Разве фоновая служба не подходит для версий Android, таких как 4.4, 5.0, 6.0.1 (версии API 19, 21, 23 и т. д.)? Я имею в виду, что если вы где-нибудь будете искать информацию о фоновых задачах, первое, что вы найдете, это Служба или Служба намерений. - person Waqas Ahmed; 27.05.2018
comment
Фоновая служба предназначена для выполнения долговременных задач, таких как загрузка/загрузка файлов и потоковая передача фоновой музыки. Для запуска периодической задачи рекомендуемый подход (от Google) — использовать Диспетчер работ. Если вы дадите мне более подробную информацию о том, чего конкретно вы пытаетесь достичь, я могу помочь больше. Как часто вы пытаетесь запустить эту задачу и что она пытается выполнить? - person Shmuel; 28.05.2018
comment
хорошо, я хочу установить соединение клиентского сокета с сокетом сервера. Приложение запускает клиентский сокет (простой сокет) и ищет серверный сокет (работает где-то еще) для подключения. если клиентский сокет соединен с серверным сокетом, то определенное сообщение проходит от сервера к клиенту и наоборот. дело в том, что мне нужна фоновая служба, потому что я хочу, чтобы клиентская служба постоянно искала серверный сокет, если приложение открыто или нет. - person Waqas Ahmed; 28.05.2018
comment
Это не сработает. Вам нужно использовать Push-сообщения (например, Firebase Cloud Messaging (FCM)), чтобы сообщить этому клиенту, что есть новые данные для синхронизации. Вы не можете держать сокет открытым. По многим причинам первые фоновые сервисы запрещены на Android O и выше. Во-вторых, ваш сервис можно убить даже на старых версиях андроида. В-третьих, вы довольно быстро разрядите аккумулятор пользователя, если оставите сетевое соединение открытым. Возможно, и другие причины... Ваш вопрос выглядит точно так же, как этот stackoverflow.com/questions/50552136/ - person Shmuel; 29.05.2018
comment
Спасибо за Ваш ответ. позвольте мне объяснить это вашему дальнейшему. У меня есть java-приложение (как служба рабочего стола) на компьютере с Windows, на котором запущен серверный сокет. Мне действительно нужно установить соединение и связь между настольным приложением java и мобильным приложением (клиентский сокет) через определенный порт. Это что-то вроде связи через сокет по сети. Что происходит, так это то, что клиентский сокет постоянно прослушивает определенный порт для серверного сокета, и когда я запускаю службу рабочего стола, связь устанавливается между обоими сокетами (между приложением и службой рабочего стола). - person Waqas Ahmed; 29.05.2018
comment
Теперь для вышеуказанной ситуации скажите мне, что я должен делать? и мне нужно выполнить этот процесс связи примерно для 3 устройств (3 разных настольных сервиса и 3 разных мобильных приложения на разных мобильных устройствах) одновременно - person Waqas Ahmed; 29.05.2018