GHC имеет расширение StandaloneDeriving
, с этим вы можете
{-# LANGUAGE StandaloneDeriving #-}
import MoneyModule
deriving instance Read Money
выводить экземпляры для многих классов.
Я исследовал это на пару дней и получил решение. Теперь в 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
}
}
Аналогично 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)
, прежде чем он был уничтожен ...
Эта ошибка также возникает на Android 8+, когда вызывается Service.startForeground (int id, уведомление уведомления) , а id - 0.
id int : Идентификатор этого уведомления в соответствии с NotificationManager.notify (int, Notification); не должно быть 0.
Проблема с 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);
Из документов Google в изменения поведения Android 8.0 :
Система позволяет приложениям вызывать Context.startForegroundService (), даже когда приложение находится в фоновом режиме. Однако приложение должно вызвать метод startForeground () этого сервиса в течение пяти секунд после создания службы.
Решение: вызвать startForeground в Oncreate () для службы, в которой используется Context.startForegroundService ( ).
См. также: Пределы выполнения фона для Android 8.0 (Oreo)
onStartCommand
, но я все еще получаю эту ошибку. Я назвал startForegroundService(intent)
в своем MainActivity
. Возможно, сервис запущен слишком медленно. Я думаю, что пятисекундный предел не должен существовать, прежде чем они смогут обещать, что сервис запускается немедленно.
– Kimi Chiu
3 October 2017 в 15:04
Даже после вызова 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 Если служба не была запущена, она сначала запускает службу, которая является накладными расходами.
Я вызвал 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);
}
}
onCreate
через 5 секунд. Поэтому они должны перепроектировать его, прежде чем заставить нас следовать правилам.
– Kimi Chiu
18 October 2017 в 06:08
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());
}
}
Я знаю, что это поздний ответ, но, я думаю, это может помочь в будущем, я просто использовал JobIntentService
вместо IntentService
, которые включают его JobScheduler и обрабатывают все для меня. посмотрите на этот пример
Я столкнулся с той же проблемой, и после того, как потратил время, нашел солитоны, вы можете попробовать под кодом. Если вы используете 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);
}
Так много ответов, но никто не работал в моем случае.
Я начал службу следующим образом.
blockquote>if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(intent); } else { startService(intent); }
И в моей службе в onStartCommand
blockquote>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;
blockquote>SO все было идеально, но все еще сбой на 8.1, поэтому причина была такой, как показано ниже.
blockquote>if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { stopForeground(true); } else { stopForeground(true); }
Я вызвал остановку переднего плана с удалением notificaton, но как только уведомление удалило сервис, фоновая и фоновая служба не могут работать в android O из фона.
Итак, магическое слово
blockquote>stopSelf();
До сих пор всякая причина, по которой ваша служба рушится, выполняет все вышеуказанные шаги и пользуется.
Это все исчезнет, если вы перезапишите свою службу для запуска w / bindService.
Пример того, как это сделать, можно увидеть по адресу: https://github.com/paulpv / ForegroundServiceAPI26 / tree / bound
Разница моей ветви «воспроизведения» можно увидеть по адресу: https://github.com/paulpv/ForegroundServiceAPI26/compare/repro .. .bound? расширить = 1
Просто голова, так как я потратил слишком много часов на это. Я продолжал получать это исключение, хотя я назвал startForeground(..)
первым делом в onCreate(..)
. В конце концов я обнаружил, что проблема была вызвана использованием NOTIFICATION_ID = 0
. Использование любого другого значения, похоже, исправить это.
StartForeground(0, notification);
не должно выбрасывать "this & quot; исключение, исключение было бы прекрасным, так как документы не заявили, что не использовать 0
(... не должно быть 0.`), но сообщение настолько вводит в заблуждение.
– SushiHangover
24 May 2018 в 05:17
Почему эта проблема происходит из-за того, что Android framework не может гарантировать, что ваш сервис начнется в течение 5 секунд, но, с другой стороны, у рамки есть строгий предел для уведомления переднего плана, который должен быть запущен в течение 5 секунд без проверки того, запустите службу.
Это определенно проблема с каркасом, но не все разработчики, сталкивающиеся с этой проблемой, делают все возможное:
При всех выше 3 эта проблема может быть уменьшена, но все же не исправлена, реальное исправление или, скажем, обходное решение это понизить вашу целевую версию sdk до 25.
И обратите внимание, что, скорее всего, Android P будет это не будет связано с тем, что Google отказывается даже понять, что происходит, и не считает, что это их вина, читайте здесь 36: https://issuetracker.google.com/issues/76112072 .