Приложение keep Crashing on Oreo: android.app.RemoteServiceException: Context.startForegroundService () не вызывал Service.startForeground () [duplicate]

GHC имеет расширение StandaloneDeriving, с этим вы можете

{-# LANGUAGE StandaloneDeriving #-}
import MoneyModule

deriving instance Read Money

выводить экземпляры для многих классов.

71
задан NiceGuy 8 June 2017 в 02:35
поделиться

15 ответов

Я исследовал это на пару дней и получил решение. Теперь в Android O вы можете установить ограничение фона как ниже

Служба, вызывающая класс обслуживания

Intent serviceIntent = new Intent(SettingActivity.this,DetectedService.class);
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){

                        SettingActivity.this.startForegroundService(serviceIntent);
                    }else{
                        startService(serviceIntent);
                    }

и класс обслуживания, должна быть как

public class DetectedService extends Service { 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        int NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(NOTIFICATION_ID, new Notification.Builder(this).build());
        }


        // Do whatever you want to do here
    }
}
3
ответ дан Ahmad Arslan 15 August 2018 в 18:41
поделиться
  • 1
    Вы пробовали его в каком-то приложении, которое имеет как минимум несколько тысяч пользователей? Я попытался, некоторые пользователи по-прежнему имеют проблемы с сбоем. – Alex 29 April 2018 в 08:37
  • 2
    Нет, я использую точный код, и я не вижу, чтобы клиенты терпели крах. – Ahmad Arslan 30 April 2018 в 07:35
  • 3
    Сколько у вас пользователей? Я видел ~ 10-30 + сбои ежедневно (с ошибкой) в приложении, в котором было 10 тыс. Пользователей в день. Конечно, это происходит только для пользователей с Android 8.0 и android 8.1, если targetSdkVersion равно 27. Все проблемы исчезают до 0 сбоев сразу после того, как я установил targetSdkVersion в 25. – Alex 30 April 2018 в 09:11
  • 4
    только 2200 пользователей: - / но не получил никакого сбоя – Ahmad Arslan 30 April 2018 в 10:08
  • 5
    @Jeeva, не совсем. Atm, я использую targetSdkVersion 25 с compileSdkVersion 27. Он выглядит лучше всего после множества экспериментов. Надеюсь, они закончат developer.android.com/topic/libraries/architecture/… до Август 2018, потому что android-developers.googleblog.com/2017/12/… – Alex 13 June 2018 в 08:55

https://developer.android.com/reference/android/content/Context.html#startForegroundService (android.content.Intent)

Аналогично startService (Intent), но с неявным обещанием, что Служба вызовет startForeground (int, android.app.Notification) после ее запуска. Для этого службе предоставляется количество времени, сопоставимое с интервалом ANR, в противном случае система автоматически остановит службу и объявит ANR приложения.

В отличие от обычного startService (Intent), этот метод может быть используется в любое время независимо от того, находится ли приложение, обслуживающее службу, в переднем плане.

убедитесь, что вы вызываете Service.startForeground(int, android.app.Notification) в onCreate (), чтобы убедиться, что он будет вызван Если у вас есть какие-либо условия, которые могут помешать вам это сделать, вам лучше использовать обычный Context.startService(Intent) и вызывать Service.startForeground(int, android.app.Notification) самостоятельно.

Кажется, что Context.startForegroundService() добавляет сторожевой таймер, чтобы убедиться, что вы вызвали Service.startForeground(int, android.app.Notification), прежде чем он был уничтожен ...

3
ответ дан Alécio Carvalho 15 August 2018 в 18:41
поделиться
  • 1
    Моя служба использует AlarmManager для запуска службы в определенное время, а затем для проверки обновлений. Теперь я вынужден использовать startForegroundService (), потому что в противном случае я не буду запускаться на Android O («W / ActivityManager: запуск фона не допускается: служебное намерение») - см. stackoverflow.com/questions/45016174/… . Как это решить? В моем случае я не всегда хочу отправлять уведомления. Если нет Интернета, я просто хочу прекратить обслуживание и ничего не показывать. – Mike Keskinov 12 February 2018 в 18:11
  • 2
    Подобные беды! Моя бизнес-логика всегда передавала уведомление моей службе через startService Intent и обрабатывала ее в onStartCommand, никогда не создавая. У меня есть журналы Crashlytics, говорящие: «Context.startForegroundService () не вызывал Service.startForeground ()», даже если startForeground вызывается в onStartCommand. Главная основа нескольких приложений, над которыми я работаю, полностью запущена! :( – swooby 21 March 2018 в 23:44
  • 3

Эта ошибка также возникает на Android 8+, когда вызывается Service.startForeground (int id, уведомление уведомления) , а id - 0.

id int : Идентификатор этого уведомления в соответствии с NotificationManager.notify (int, Notification); не должно быть 0.

1
ответ дан almisoft 15 August 2018 в 18:41
поделиться

Проблема с Android O API 26

Если вы остановите услугу сразу (поэтому ваша служба фактически не работает (формулировка / понимание), и вы находитесь под интервалом ANR, вам все равно нужно call startForeground перед stopSelf

https://plus.google.com/116630648530850689477/posts/L2rn4T6SAJ5

Пробовал этот подход Но он все еще создает ошибку: -

if (Util.SDK_INT > 26) {
    mContext.startForegroundService(playIntent);
} else {
    mContext.startService(playIntent);
}

Я использую это, пока не будет устранена ошибка

mContext.startService(playIntent);
0
ответ дан Andy Cass 15 August 2018 в 18:41
поделиться

Из документов Google в изменения поведения Android 8.0 :

Система позволяет приложениям вызывать Context.startForegroundService (), даже когда приложение находится в фоновом режиме. Однако приложение должно вызвать метод startForeground () этого сервиса в течение пяти секунд после создания службы.

Решение: вызвать startForeground в Oncreate () для службы, в которой используется Context.startForegroundService ( ).

См. также: Пределы выполнения фона для Android 8.0 (Oreo)

32
ответ дан Cody Gray 15 August 2018 в 18:41
поделиться
  • 1
    Я сделал это в методе onStartCommand, но я все еще получаю эту ошибку. Я назвал startForegroundService(intent) в своем MainActivity. Возможно, сервис запущен слишком медленно. Я думаю, что пятисекундный предел не должен существовать, прежде чем они смогут обещать, что сервис запускается немедленно. – Kimi Chiu 3 October 2017 в 15:04
  • 2
    5 секундного периода определенно недостаточно, это исключение случается очень часто в сеансах отладки. Я подозреваю, что это также произойдет в режиме выпуска время от времени. И будучи FATAL EXCEPTION, это просто сбой приложения! Я попытался поймать его с помощью Thread.setDefaultUncaughtExceptionHandler (), но даже при получении его и игнорировании андроида зависает приложение. Это потому, что это исключение запускается из handleMessage (), и основной цикл эффективно заканчивается ... ищет обходной путь. – southerton 20 March 2018 в 16:48
  • 3
    @zhuzhumouse Пожалуйста, отправьте ответ с примером кода, по крайней мере, вы – Ahmad Arslan 5 April 2018 в 10:53
  • 4
    Я вызвал метод Context.startForegroundService () в широковещательном приемнике. так как обращаться в этой ситуации? потому что onCreate () недоступен в широковещательном приемнике – Anand Savjani 12 July 2018 в 14:49

Даже после вызова startForeground в Service он сбой на некоторых устройствах, если мы вызываем stopService непосредственно перед вызовом onCreate. Итак, я исправил эту проблему, запустив службу с дополнительным флагом:

Intent intent = new Intent(context,
                YourService.class);
intent.putExtra("request_stop", true);
context.startService(intent);

и добавил проверку onStartCommand, чтобы проверить, действительно ли она была остановлена:

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

    //call startForeground first
    boolean stopService = false;
    if (intent != null) {
        stopService = intent.getBooleanExtra("request_stop", false);
    }
    if (stopService) {
        stopSelf();
        return START_STICKY;
    }
    //Continue with the background task
    return START_STICKY;
}

PS Если служба не была запущена, она сначала запускает службу, которая является накладными расходами.

0
ответ дан Gaurav Singla 15 August 2018 в 18:41
поделиться

Я вызвал ContextCompat.startForegroundService(this, intent), чтобы запустить службу, затем

В службе onCreate

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

        if (Build.VERSION.SDK_INT >= 26) {
            String CHANNEL_ID = "my_channel_01";
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Channel human readable title",
                    NotificationManager.IMPORTANCE_DEFAULT);

            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("")
                    .setContentText("").build();

            startForeground(1, notification);
        }
}
28
ответ дан humazed 15 August 2018 в 18:41
поделиться
  • 1
    Я тоже. Но иногда я получаю эту ошибку. Возможно, Android не может гарантировать, что он вызовет onCreate через 5 секунд. Поэтому они должны перепроектировать его, прежде чем заставить нас следовать правилам. – Kimi Chiu 18 October 2017 в 06:08
  • 2
    Я вызывал startForeground в onStartCommand (), и я иногда получал эту ошибку. Я переместил его в onCreate, и я не видел его с тех пор (пересекая пальцы). – Tyler 13 December 2017 в 20:06
  • 3
    Это создает локальное уведомление в Oreo, говорящее «APP_NAME». Нажмите, чтобы закрыть или просмотреть информацию. Как прекратить показ этого уведомления? – Artist404 14 December 2017 в 13:20
  • 4
    Нет, команда Android заявила, что это предполагаемое поведение. Поэтому я просто переработал свое приложение. Это нелепо. Всегда необходимо перепроектировать приложения из-за этих «предполагаемых действий». Это уже третий раз. – Kimi Chiu 12 January 2018 в 12:16
  • 5
    Основная причина этой проблемы - это остановка службы, прежде чем она будет переведена на передний план. Но это утверждение не прекращалось после того, как служба была уничтожена. Вы можете попытаться воспроизвести это, добавив StopService после вызова startForegroundService. – Kimi Chiu 12 January 2018 в 12:20

Убедитесь, что все пути кода вызывает метод startForeground, например, код может генерировать исключение в методе onCreate вашего сервиса, который предотвращает вызов startForeground

   @Override
    public void onCreate() {
try{
}
catch(Exception e)
{
}
finally{
    startForeground(1, notificationbuilder.build());

}
    }
-1
ответ дан Mohamed Gaafar 15 August 2018 в 18:41
поделиться

Я знаю, что это поздний ответ, но, я думаю, это может помочь в будущем, я просто использовал JobIntentService вместо IntentService, которые включают его JobScheduler и обрабатывают все для меня. посмотрите на этот пример

0
ответ дан raed 15 August 2018 в 18:41
поделиться

Я столкнулся с той же проблемой, и после того, как потратил время, нашел солитоны, вы можете попробовать под кодом. Если вы используете Service, тогда установите этот код в onCreate else, используя Intent Service, затем поместите этот код в onHandleIntent.

if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_app";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "MyApp", NotificationManager.IMPORTANCE_DEFAULT);
        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();
        startForeground(1, notification);
    }
1
ответ дан Sambhaji Karad 15 August 2018 в 18:41
поделиться

Так много ответов, но никто не работал в моем случае.

Я начал службу следующим образом.

              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                } else {
                    startService(intent);
                }

И в моей службе в onStartCommand

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText("SmartTracker Running")
                .setAutoCancel(true);
        Notification notification = builder.build();
        startForeground(NOTIFICATION_ID, notification);
    } else {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setContentTitle(getString(R.string.app_name))
                .setContentText("SmartTracker is Running...")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true);
        Notification notification = builder.build();
        startForeground(NOTIFICATION_ID, notification);
    }

И не забудьте установить NOTIFICATION_ID non zero

private static final String ANDROID_CHANNEL_ID = "com.xxxx.Location. канал "; private static final int NOTIFICATION_ID = 555;

SO все было идеально, но все еще сбой на 8.1, поэтому причина была такой, как показано ниже.

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            stopForeground(true);
        } else {
            stopForeground(true);
        }

Я вызвал остановку переднего плана с удалением notificaton, но как только уведомление удалило сервис, фоновая и фоновая служба не могут работать в android O из фона.

Итак, магическое слово

  stopSelf();

До сих пор всякая причина, по которой ваша служба рушится, выполняет все вышеуказанные шаги и пользуется.

0
ответ дан sandy 15 August 2018 в 18:41
поделиться

Это все исчезнет, ​​если вы перезапишите свою службу для запуска w / bindService.

Пример того, как это сделать, можно увидеть по адресу: https://github.com/paulpv / ForegroundServiceAPI26 / tree / bound

Разница моей ветви «воспроизведения» можно увидеть по адресу: https://github.com/paulpv/ForegroundServiceAPI26/compare/repro .. .bound? расширить = 1

7
ответ дан swooby 15 August 2018 в 18:41
поделиться
  • 1
    Связывание ошибки здесь было плохим шагом. Благодаря всем глупцам, публикующим свой сломанный код и несколько сообщений, дублирующих свои собственные ошибки, которые они уже разместили здесь, билет беспорядок и, скорее всего, будет закрыт: / – Nick Cardoso 21 May 2018 в 08:35
  • 2
    Да, распространение достоверной информации в виде репрограммного кода и открытие ошибки и привязка к ней здесь ужасно. Я думаю, сегодня кто-то проснулся на неправильной стороне кровати. – swooby 22 May 2018 в 17:16
  • 3
    Я не знаю, почему это было приостановлено. Если вы пробовали все другие решения и по-прежнему получаете ошибку, и у вас есть возможность привязываться к службе, тогда это ответ только до тех пор, пока AOSP не устранит основную проблему. – swooby 22 May 2018 в 17:25
  • 4
    @swooby Получили ли вы какие-либо обновления по этому вопросу? – Gaurav Singla 22 June 2018 в 06:47
  • 5
    Лучшее обновление, которое я видел, - issuetracker.google.com/issues/76112072#comment56 . Я переписал свой код для использования Context.bindService, который полностью избегает проблемного вызова Context.startForegroundService. Вы можете увидеть мой пример кода в github.com/paulpv/ForegroundServiceAPI26/tree/bound/app/src/… – swooby 22 June 2018 в 21:37
  • 6
    Я не ответил на ваш ответ, но, пожалуйста, имейте в виду, что может возникнуть необходимость запустить службу с помощью startService () - например, когда вам нужно ее запустить, пока ваша активность не отображается. – Yar 6 July 2018 в 09:59
  • 7
    @Yar, который он делает до тех пор, пока вызывается Service.startForeground. С тех пор я узнал, что Service.startForeground только документально оформлен для работы с «Начатые службы», но в настоящее время , похоже, работает только для поиска связанных служб. – swooby 9 July 2018 в 22:24
  • 8
    Ты прав. Я вижу, что я сам запускаю службу следующим образом: if (android.os.Build.VERSION.SDK_INT & gt; = Build.VERSION_CODES.O) startForegroundService (mServiceIntent); else startService (mServiceIntent); и затем я привязываюсь к нему. – Yar 11 July 2018 в 07:45

Просто голова, так как я потратил слишком много часов на это. Я продолжал получать это исключение, хотя я назвал startForeground(..) первым делом в onCreate(..). В конце концов я обнаружил, что проблема была вызвана использованием NOTIFICATION_ID = 0. Использование любого другого значения, похоже, исправить это.

3
ответ дан tobalr 15 August 2018 в 18:41
поделиться
  • 1
    Спасибо .... Использование нуля в StartForeground(0, notification); не должно выбрасывать "this & quot; исключение, исключение было бы прекрасным, так как документы не заявили, что не использовать 0 (... не должно быть 0.`), но сообщение настолько вводит в заблуждение. – SushiHangover 24 May 2018 в 05:17

Почему эта проблема происходит из-за того, что Android framework не может гарантировать, что ваш сервис начнется в течение 5 секунд, но, с другой стороны, у рамки есть строгий предел для уведомления переднего плана, который должен быть запущен в течение 5 секунд без проверки того, запустите службу.

Это определенно проблема с каркасом, но не все разработчики, сталкивающиеся с этой проблемой, делают все возможное:

  1. startForeground уведомление должно быть как в onCreate, так и onStartCommand , потому что, если ваша служба уже создана, и как-то ваша активность пытается ее запустить снова, onCreate не будет вызываться.
  2. идентификатор уведомления не должен быть 0, в противном случае произойдет один и тот же сбой, даже если это не та же причина.
  3. stopSelf не нужно вызывать перед startForeground.

При всех выше 3 эта проблема может быть уменьшена, но все же не исправлена, реальное исправление или, скажем, обходное решение это понизить вашу целевую версию sdk до 25.

И обратите внимание, что, скорее всего, Android P будет это не будет связано с тем, что Google отказывается даже понять, что происходит, и не считает, что это их вина, читайте здесь 36: https://issuetracker.google.com/issues/76112072 .

4
ответ дан ZhouX 15 August 2018 в 18:41
поделиться
  • 1
    Почему и onCreate, и onStartCommand? Можете ли вы просто положить его в onStartCommand? – rcell 6 August 2018 в 21:10
9
ответ дан swooby 5 September 2018 в 17:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: