No lançamento do aplicativo, o aplicativo inicia o serviço que deve executar algumas tarefas de rede. Depois de segmentar o nível 26 da API, meu aplicativo falha ao iniciar o serviço no Android 8.0 em segundo plano.
Causado por: java.lang.IllegalStateException: Não é permitido iniciar o serviço Intenção {cmp = my.app.tt / com.my.service}: o aplicativo está em segundo plano uid UidRecord {90372b1 u0a136 CEM ids procs: 1 seq (0,0 , 0)}
como eu o entendo relacionado a: Limites de execução em segundo plano
O método startService () agora lança uma IllegalStateException se um aplicativo direcionado ao Android 8.0 tentar usar esse método em uma situação em que não é permitido criar serviços em segundo plano.
" em uma situação em que não é permitido " - o que realmente significa? E como consertar isso. Não quero definir meu serviço como "primeiro plano"
startForegroundService()
vez destartService()
.Respostas:
As situações permitidas são uma lista branca temporária em que o serviço em segundo plano se comporta da mesma maneira que antes do Android O.
Fonte: https://developer.android.com/about/versions/oreo/background.html
Portanto, em outras palavras, se o serviço em segundo plano não atender aos requisitos da lista de desbloqueio, você precisará usar o novo JobScheduler . É basicamente o mesmo que um serviço em segundo plano, mas é chamado periodicamente em vez de ser executado em segundo plano continuamente.
Se você estiver usando um IntentService, poderá mudar para um JobIntentService. Veja a resposta de @ kosev abaixo .
fonte
FirebaseInstanceIdService
e éonTokenRefresh
uma mensagem FCM de alta prioridade?Eu tenho solução. Para dispositivos anteriores à 8.0, você precisa apenas usar
startService()
, mas para dispositivos posteriores à 7.0, você deve usarstartForgroundService()
. Aqui está um exemplo de código para iniciar o serviço.E na classe de serviço, adicione o código abaixo para notificação:
Onde O é a versão 26 do Android.
fonte
ContextCompat.startForegroundService(...)
biblioteca de suporte que pode ser usada em seu lugar.A melhor maneira é usar JobIntentService, que usa o novo JobScheduler for Oreo ou os serviços antigos, se não disponíveis.
Declare no seu manifesto:
E em seu serviço, você deve substituir onHandleIntent por onHandleWork:
Então você inicia seu serviço com:
fonte
enqueueWork(...)
é um método estático.Se o serviço estiver sendo executado em um encadeamento em segundo plano, estendendo
IntentService
, você poderá substituirIntentService
porJobIntentService
que é fornecido como parte da Biblioteca de suporte AndroidA vantagem de usar
JobIntentService
é que ele se comporta como umIntentService
em dispositivos pré-O e em O e superior, ele o envia como um trabalhoJobScheduler
também pode ser usado para trabalhos periódicos / sob demanda. Mas assegure-se de lidar com a compatibilidade com versões anteriores, pois aJobScheduler
API está disponível apenas na API 21fonte
No Oreo, o Android definiu limites para os serviços em segundo plano .
Ainda assim, se você precisar sempre executar o serviço, poderá usar o serviço em primeiro plano.
Então você pode fazer um serviço em primeiro plano . Você precisará mostrar uma notificação ao usuário quando seu serviço estiver sendo executado. Veja esta resposta (existem muitas outras)
Uma solução se -
você não quer uma notificação para o seu serviço?
Você pode usar tarefas periódicas com o Alarm Manager , o Job Scheduler , o Evernote-Jobs ou o Work Manager .
Eu testei o serviço para sempre em execução com o Work-Manager.
fonte
Sim, é porque você não pode mais iniciar serviços em segundo plano na API 26. Portanto, você pode iniciar o ForegroundService acima da API 26.
Você terá que usar
e publique uma notificação ao processar o vazamento.
fonte
Como @kosev disse em sua resposta, você pode usar o JobIntentService. Mas eu uso uma solução alternativa - eu pego o IllegalStateException e inicio o serviço como primeiro plano. Por exemplo, esta função inicia meu serviço:
e quando processo Intent, faço o seguinte:
fonte
context.startService
trabalha em fundo - às vezes não - esta parece ser a única melhor maneira de outra forma você tem que implementar mais código em sua classe principalextending Application
eimplementing ActivityLifecycleCallbacks
e acompanhar se o aplicativo está em primeiro ou segundo plano e começar a sua intenção adequadamente.Nas notas de versão do firebase , eles afirmam que o suporte ao Android O foi lançado pela primeira vez na versão 10.2.1 (embora eu recomende o uso da versão mais recente).
adicione novas dependências de mensagens do firebase para o Android O
atualize os serviços do Google Play e os repositórios do Google, se necessário.
fonte
Se alguma intenção estava funcionando bem quando o aplicativo está em segundo plano, não será mais o caso do Android 8 e posterior. Referindo-se apenas à intenção que precisa fazer algum processamento quando o aplicativo estiver em segundo plano.
Os passos abaixo devem ser seguidos:
JobIntentService
vez deIntentService
.A classe que se estende
JobIntentService
deve implementar oonHandleWork(@NonNull Intent intent)
método - e deve ter abaixo do método, o que invocará oonHandleWork
método:Ligue
enqueueWork(Context, intent)
da classe onde sua intenção está definida.Código de amostra:
com.android.support:support-compat
é necessário paraJobIntentService
- eu uso26.1.0 V
.O mais importante é garantir que a versão das bibliotecas do Firebase esteja no mínimo
10.2.1
, tive problemas com10.2.0
- se você tiver algum!Seu manifesto deve ter a permissão abaixo para a classe Service:
Espero que isto ajude.
fonte
Vejo muitas respostas que recomendam apenas o uso de um ForegroundService. Para usar um ForegroundService, deve haver uma notificação associada a ele. Os usuários verão esta notificação. Dependendo da situação, eles podem ficar irritados com o aplicativo e desinstalá-lo.
A solução mais fácil é usar o novo componente de arquitetura chamado WorkManager. Você pode conferir a documentação aqui: https://developer.android.com/topic/libraries/architecture/workmanager/
Você acabou de definir sua classe de trabalhador que estende o Trabalhador.
Em seguida, você agende quando deseja executá-lo.
Fácil! Existem várias maneiras de configurar trabalhadores. Ele suporta trabalhos recorrentes e você pode até fazer coisas complexas, como encadeamento, se precisar. Espero que isto ajude.
fonte
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately
... pode ser mais fácil, no entanto, meu aplicativo precisa de um serviço em segundo plano que execute as solicitações dos usuários imediatamente!Solução alternativa usando o JobScheduler, ele pode iniciar o serviço em segundo plano em um intervalo regular de tempo.
Em primeiro lugar, faça a classe denominada Util.java
Em seguida, torne a classe JobService denominada TestJobService.java
Depois dessa classe BroadCast Receiver chamada ServiceReceiver.java
Atualizar arquivo de manifesto com código de classe de serviço e receptor
O ativador main_intent esquerdo para o arquivo mainActivity.java, criado por padrão, e as alterações no arquivo MainActivity.java são
WOOAAH !! O serviço em segundo plano é iniciado sem o serviço de primeiro plano
fonte
Se você estiver executando seu código na 8.0, o aplicativo falhará. Portanto, inicie o serviço em primeiro plano. Se abaixo de 8.0, use isto:
Se acima ou 8.0, use o seguinte:
fonte
java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE
. Corrigir stackoverflow.com/a/52382711/550471se você tiver integrado a notificação por push do sistema de mensagens do firebase,
Adicione novas / atualize dependências de mensagens do firebase para o Android O (Android 8.0), devido a limites de execução em segundo plano .
atualize os serviços do Google Play e os repositórios do Google, se necessário.
Atualizar:
fonte
Use em
startForegroundService()
vez destartService()
e não esqueça de criarstartForeground(1,new Notification());
no seu serviço dentro de 5 segundos após iniciar o serviço.fonte
Devido a votos controversos nesta resposta (+ 4 / -4 a partir desta edição), VEJA AS OUTRAS RESPOSTAS PRIMEIRAMENTE E USE ISSO SOMENTE COMO ÚLTIMO RECURSO . Eu usei isso apenas uma vez para um aplicativo de rede que roda como root e concordo com a opinião geral de que esta solução não deve ser usada em circunstâncias normais.
Resposta original abaixo:
As outras respostas estão todas corretas, mas gostaria de salientar que outra maneira de contornar isso é pedir ao usuário que desative as otimizações de bateria do seu aplicativo (isso geralmente não é uma boa ideia, a menos que o aplicativo esteja relacionado ao sistema). Veja esta resposta para saber como solicitar a desativação das otimizações da bateria sem que seu aplicativo seja banido no Google Play.
Você também deve verificar se as otimizações da bateria estão desativadas no seu receptor para evitar falhas através de:
fonte
JobScheduler
e outras coisas. Alguns aplicativos precisam funcionar em um nível mais baixo do que os aplicativos de sincronização típicos. Esta é uma solução alternativa quando isso não funciona.não use no onStartCommand:
basta alterá-lo para:
e vai funcionar
fonte