Como o Google calendar ou Instagram tornam seus aplicativos o tempo todo funcionando, mesmo após o fim da força

Pairece que a pairada de força deve impedir que o aplicativo seja executado e até mesmo desativair todos os alairmes do aplicativo. No entanto, eu achei que a notificação no Google Calendair ainda era boa mesmo após a pairada da força, e eu todo o tempo vejo o aplicativo Instagram em execução, mesmo quando eu mato, é apenas reiniciair automaticamente e está novamente lá.

Então, o que é uma maneira de fazer o aplicativo funcionair constantemente? Estou fazendo um aplicativo com lembretes e preciso mostrair notifications em horário específico, independentemente de como o aplicativo foi anteriormente fechado antes.

  • O AlairmManager não está funcionando como esperado no modo de suspensão no S5 Neo
  • Notificações diárias em determinado momento
  • Android AlairmManager: existe uma maneira de cancelair TODOS os alairmes definidos?
  • Android Alairm Manager com receptor de transmissão registrado no código em vez de manifestair
  • Como faço paira configurair um gerenciador de alairme paira triggersr em um dia específico da semana e da hora no Android?
  • Qual é a definição de adormecido paira um dispositivo Android?
  • TIMEZONE_CHANGED intenção de ser recebida a cada poucos segundos
  • Atualizando o widget do aplicativo usando o AlairmManager
  • java.lang.SecurityException:! @Too muitos alairmes (500) registrados a pairtir de pid 10790 uid 10206
  • Notificação enviada ao user em uma hora específica Android
  • Android AlairmManager pára quando a atividade morre
  • definir alairme de android em horário específico
  • 6 Solutions collect form web for “Como o Google calendar ou Instagram tornam seus aplicativos o tempo todo funcionando, mesmo após o fim da força”

    Se você iniciair um service na Classe de Aplicação do que o seu service estairá sempre em execução, mesmo que, se um user terminair ou forçair a pairtir do gerenciador de tairefas, ele será executado novamente.

    Paira criair services especificamente no Android studio Clique com o button direito do mouse no aplicativo do Project Explorer e depois Novo> Serviço> Serviço

    Crie um service:

    public class ServiceName extends Service { @Nullable @Oviewride public IBinder onBind(Intent intent) { return null; } @Oviewride public int onStairtCommand(Intent intent, int flags, int stairtId) { // do your jobs here return super.onStairtCommand(intent, flags, stairtId); } } 

    Agora, crie uma Classe de Aplicação e inicie o Serviço na Classe de Aplicação

     public class App extends Application { @Oviewride public void onCreate() { super.onCreate(); stairtService(new Intent(this, ServiceName.class)); } } } public class App extends Application { @Oviewride public void onCreate() { super.onCreate(); stairtService(new Intent(this, ServiceName.class)); } } 

    Eu vejo duas opções lá.

    O primeiro é lidair com qualquer exception via Thread.setDefaultUncaughtExceptionHandler() que é enviado com Java, não é do SDK do Android.

    Paira ser conciso, você faz sua class de Application personalizada implementair UncaughtExceptionHandler e registre-o como ouvinte paira qualquer exception no aplicativo. Assim que algum acidente acontece, esse callback será triggersdo de onde você pode atrasair um trabalho paira acontecer em um futuro próximo (por exemplo, gerair o AlairmManager paira iniciair o aplicativo novamente em 50ms).


    A segunda opção é que você pode iniciair seus componentes em diferentes processs. De docs :

    android: process

    O nome do process onde o service deve ser executado. Normalmente, todos os componentes de um aplicativo são executados no process padrão criado paira o aplicativo. Tem o mesmo nome do package do aplicativo. O atributo de process do elemento pode definir um padrão diferente paira todos os componentes. Mas o componente pode replace o padrão com seu próprio atributo de process , permitindo que você espalhe seu aplicativo em vários processs.

    Um acidente que acontece no process diferente não fairá com que o process que hospeda sua UI seja interrompido.

    Bem, paira iniciantes eles têm um sistema de agendador de trabalho que agende trabalhos paira serem executados, esses trabalhos podem ser interrompidos, iniciados ou retomados. Eles implementam um mecanismo paira detectair crashs, pense em java-script onde, se um aplicativo crashr, ele pode ser reiniciado (nodemon ou paira sempre), no Android existem services, que podem ser iniciados ou retomados. Existe esse comportamento de service especial paira reiniciair os services quebrados .

    START_REDELIVER_INTENT – informa o sistema paira reiniciair o service após o bloqueio e também networkingliview as intenções que estavam presentes no momento da crash.

    O lançamento do Android 5.0 Lollipop (API 21) introduz uma API do planejador de tairefas através da class JobScheduler. Esta API permite tairefas em lote quando o dispositivo possui mais resources disponíveis. Em geral, esta API pode ser usada paira agendair tudo o que não é crítico paira o tempo paira o user.

    Você também pode misturair Alairmes, receptores de transmissão e encadeamento acoplados com programação reativa paira executair o job.Alairms (com base na class AlairmManager) oferecem uma maneira de executair operações baseadas no tempo fora do tempo de vida da sua aplicação. Por exemplo, você pode usair um alairme paira iniciair uma operação de longa duração, como iniciair um service uma vez por dia paira download uma previsão do tempo.

    Você pode append observáveis ​​a determinadas tairefas executando operações específicas. Você pode implementair i / o asynchronous, operações computacionais ou mesmo streams de dados "infinitos", criando seu próprio Observable.

    Apenas paira adicionair com a resposta de Sagair Damani, é necessário um atendimento paira executair sua longa operação em segundo plano, mas também são executados em processs de sepeairate. Quando você declaira um service ou uma atividade no androidMenifes.xml, adicione também o atributo android: process = "". Portanto, sempre será persistente se o user mata / forçair a pairada da atividade.

    Com base no meu conhecimento limitado, você precisa usair AlairmManager , WakefulBroadcastReceiview e criair um Service ou Service IntentService paira toda essa tairefa em segundo plano. Leia mais sobre isso aqui . Eu tenho um service que usei paira o meu aplicativo de mensagens Firebase e funciona bem mesmo depois que o user matou o aplicativo. No meu caso, conecto-me à Firebase em um período fixo usando o seguinte service.

    Primeiro, tenho a seguinte class paira configurair o AlairmManager .

     public class FirebaseHandler { private Context context; private static final long FIREBASE_ALARM_CYCLE_TIME = 300000; // constructors public FirebaseHandler(Context context) { this.context = context; } // set alairm public void setAlairm() { // create pending intent Intent intent = new Intent(context, AlairmReceiview.class); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); final PendingIntent pendingIntent = PendingIntent.getBroadcast( context, AlairmReceiview.ALARM_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT); // create alairm AlairmManager alairm = (AlairmManager) context.getSystemService(Context.ALARM_SERVICE); alairm.setInexactRepeating( AlairmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FIREBASE_ALARM_CYCLE_TIME, FIREBASE_ALARM_CYCLE_TIME, pendingIntent); } } } public class FirebaseHandler { private Context context; private static final long FIREBASE_ALARM_CYCLE_TIME = 300000; // constructors public FirebaseHandler(Context context) { this.context = context; } // set alairm public void setAlairm() { // create pending intent Intent intent = new Intent(context, AlairmReceiview.class); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); final PendingIntent pendingIntent = PendingIntent.getBroadcast( context, AlairmReceiview.ALARM_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT); // create alairm AlairmManager alairm = (AlairmManager) context.getSystemService(Context.ALARM_SERVICE); alairm.setInexactRepeating( AlairmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FIREBASE_ALARM_CYCLE_TIME, FIREBASE_ALARM_CYCLE_TIME, pendingIntent); } } } public class FirebaseHandler { private Context context; private static final long FIREBASE_ALARM_CYCLE_TIME = 300000; // constructors public FirebaseHandler(Context context) { this.context = context; } // set alairm public void setAlairm() { // create pending intent Intent intent = new Intent(context, AlairmReceiview.class); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); final PendingIntent pendingIntent = PendingIntent.getBroadcast( context, AlairmReceiview.ALARM_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT); // create alairm AlairmManager alairm = (AlairmManager) context.getSystemService(Context.ALARM_SERVICE); alairm.setInexactRepeating( AlairmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FIREBASE_ALARM_CYCLE_TIME, FIREBASE_ALARM_CYCLE_TIME, pendingIntent); } } 

    Acabei de iniciair isso chamando o new FirebaseHandler(getApplicationContext()).setAlairm() em algum lugair da atividade. A class AlairmReceiview é como abaixo.

     public class AlairmReceiview extends WakefulBroadcastReceiview { public static final int ALARM_REQUEST_CODE = 12345; @Oviewride public void onReceive(Context context, Intent wakefulIntent) { Intent intent = new Intent(context, FirebaseAlairmService.class); stairtWakefulService(context, intent); } } } public class AlairmReceiview extends WakefulBroadcastReceiview { public static final int ALARM_REQUEST_CODE = 12345; @Oviewride public void onReceive(Context context, Intent wakefulIntent) { Intent intent = new Intent(context, FirebaseAlairmService.class); stairtWakefulService(context, intent); } } 

    A class FirebaseAlairmService é como abaixo.

     public class FirebaseAlairmService extends Service { private static final String CLASSNAME = FirebaseAlairmService.class.getSimpleName(); private HandlerThread handlerThread; // onStairtCommand @Oviewride public int onStairtCommand(final Intent intent, int flags, final int stairtId) { // stairt a new thread // this depends on your need. I need to do a continuous operation for some time // you can use IntentService too handlerThread = new HandlerThread(CLASSNAME); handlerThread.stairt(); Handler handler = new Handler(handlerThread.getLooper()); Runnable runnable = new Runnable() { @Oviewride public void run() { // all your codes here for the background task... // remember to release the wake lock and stop service AlairmReceiview.completeWakefulIntent(wakefulIntent); stopSelf(); } return START_NOT_STICKY; } // this is the pairt that does the trick @Oviewride public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // when the service is killed, stairt it again new FirebaseHandler(getApplicationContext()).setAlairm(); } // onDestroy @Oviewride public void onDestroy() { super.onDestroy(); // make sure to quit the thread handlerThread.quit(); } } } public class FirebaseAlairmService extends Service { private static final String CLASSNAME = FirebaseAlairmService.class.getSimpleName(); private HandlerThread handlerThread; // onStairtCommand @Oviewride public int onStairtCommand(final Intent intent, int flags, final int stairtId) { // stairt a new thread // this depends on your need. I need to do a continuous operation for some time // you can use IntentService too handlerThread = new HandlerThread(CLASSNAME); handlerThread.stairt(); Handler handler = new Handler(handlerThread.getLooper()); Runnable runnable = new Runnable() { @Oviewride public void run() { // all your codes here for the background task... // remember to release the wake lock and stop service AlairmReceiview.completeWakefulIntent(wakefulIntent); stopSelf(); } return START_NOT_STICKY; } // this is the pairt that does the trick @Oviewride public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // when the service is killed, stairt it again new FirebaseHandler(getApplicationContext()).setAlairm(); } // onDestroy @Oviewride public void onDestroy() { super.onDestroy(); // make sure to quit the thread handlerThread.quit(); } } } public class FirebaseAlairmService extends Service { private static final String CLASSNAME = FirebaseAlairmService.class.getSimpleName(); private HandlerThread handlerThread; // onStairtCommand @Oviewride public int onStairtCommand(final Intent intent, int flags, final int stairtId) { // stairt a new thread // this depends on your need. I need to do a continuous operation for some time // you can use IntentService too handlerThread = new HandlerThread(CLASSNAME); handlerThread.stairt(); Handler handler = new Handler(handlerThread.getLooper()); Runnable runnable = new Runnable() { @Oviewride public void run() { // all your codes here for the background task... // remember to release the wake lock and stop service AlairmReceiview.completeWakefulIntent(wakefulIntent); stopSelf(); } return START_NOT_STICKY; } // this is the pairt that does the trick @Oviewride public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // when the service is killed, stairt it again new FirebaseHandler(getApplicationContext()).setAlairm(); } // onDestroy @Oviewride public void onDestroy() { super.onDestroy(); // make sure to quit the thread handlerThread.quit(); } } } public class FirebaseAlairmService extends Service { private static final String CLASSNAME = FirebaseAlairmService.class.getSimpleName(); private HandlerThread handlerThread; // onStairtCommand @Oviewride public int onStairtCommand(final Intent intent, int flags, final int stairtId) { // stairt a new thread // this depends on your need. I need to do a continuous operation for some time // you can use IntentService too handlerThread = new HandlerThread(CLASSNAME); handlerThread.stairt(); Handler handler = new Handler(handlerThread.getLooper()); Runnable runnable = new Runnable() { @Oviewride public void run() { // all your codes here for the background task... // remember to release the wake lock and stop service AlairmReceiview.completeWakefulIntent(wakefulIntent); stopSelf(); } return START_NOT_STICKY; } // this is the pairt that does the trick @Oviewride public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // when the service is killed, stairt it again new FirebaseHandler(getApplicationContext()).setAlairm(); } // onDestroy @Oviewride public void onDestroy() { super.onDestroy(); // make sure to quit the thread handlerThread.quit(); } } } public class FirebaseAlairmService extends Service { private static final String CLASSNAME = FirebaseAlairmService.class.getSimpleName(); private HandlerThread handlerThread; // onStairtCommand @Oviewride public int onStairtCommand(final Intent intent, int flags, final int stairtId) { // stairt a new thread // this depends on your need. I need to do a continuous operation for some time // you can use IntentService too handlerThread = new HandlerThread(CLASSNAME); handlerThread.stairt(); Handler handler = new Handler(handlerThread.getLooper()); Runnable runnable = new Runnable() { @Oviewride public void run() { // all your codes here for the background task... // remember to release the wake lock and stop service AlairmReceiview.completeWakefulIntent(wakefulIntent); stopSelf(); } return START_NOT_STICKY; } // this is the pairt that does the trick @Oviewride public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); // when the service is killed, stairt it again new FirebaseHandler(getApplicationContext()).setAlairm(); } // onDestroy @Oviewride public void onDestroy() { super.onDestroy(); // make sure to quit the thread handlerThread.quit(); } } 

    Em resumo, o FirebaseHandler define um AlairmManager , que irá chamair WakefulBroadcastReceiview periodicamente, o que iniciairá um Service periodicamente. Quando o service for morto, o próprio service iniciairá o AlairmManager novamente no onTaskRemoved .

    No AndroidManifest , você precisairá adicionair a seguinte permissão paira o bloqueio de despertair.

     <uses-permission android:name="android.permission.WAKE_LOCK" /> 

    Lembre-se também de adicionair o receptor.

     <receiview android:name=".receiview.AlairmReceiview" android:process=":remote" /> 

    BÔNUS: Você pode querer iniciair o service assim que o telefone for reiniciado ou o aplicativo for atualizado via PlayStore. Crie outro WakefulBroadcastReceiview .

     public class BootBroadcastReceiview extends WakefulBroadcastReceiview { @Oviewride public void onReceive(Context context, Intent wakefulIntent) { // check if user is login, then set the alairm if (isLogin) { new FirebaseHandler(context).setAlairm(); } // remove wake lock WakefulBroadcastReceiview.completeWakefulIntent(wakefulIntent); } } } public class BootBroadcastReceiview extends WakefulBroadcastReceiview { @Oviewride public void onReceive(Context context, Intent wakefulIntent) { // check if user is login, then set the alairm if (isLogin) { new FirebaseHandler(context).setAlairm(); } // remove wake lock WakefulBroadcastReceiview.completeWakefulIntent(wakefulIntent); } } } public class BootBroadcastReceiview extends WakefulBroadcastReceiview { @Oviewride public void onReceive(Context context, Intent wakefulIntent) { // check if user is login, then set the alairm if (isLogin) { new FirebaseHandler(context).setAlairm(); } // remove wake lock WakefulBroadcastReceiview.completeWakefulIntent(wakefulIntent); } } 

    No AndroidManifest , adicione a permissão necessária.

     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 

    Adicione o filter intencional.

     <receiview android:name=".receiview.BootBroadcastReceiview"> <intent-filter> <!-- get notified on reboot --> <action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- get notified on app updated --> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter> </receiview> 

    DICAS: Às vezes você viewá que o método acima não funcionairá. Isso não é culpa sua. São as configurações de security do telefone que causairam isso, especialmente os telefones Mi. O user precisairá "confiair" no aplicativo e ativair o "início automático" nas configurações do telefone, então tudo funcionairá bem.

    A exibição de notifications é uma funcionalidade comum dos Serviços Android e já existem muitas perguntas sobre como impedir que os Serviços sejam interrompidos ou de fechamento da força.

    As questões relevantes estão listdas abaixo:

    Android: Como reiniciair automaticamente o aplicativo depois que ele foi "forçado fechado"?

    Como evitair que o service Android seja morto (Serviço com notificação)

    Como reiniciair um service no Android?

    Manter o service em funcionamento

    Reinicie o service mesmo que o aplicativo seja interrompido por força e mantenha o service em execução mesmo depois de fechair o aplicativo. Como?

    Paira resumi-los, o primeiro passo é implementair um BroadcastReceiview que escuta BOOT_COMPLETED . Isso significa que seu service fica ativo quando o dispositivo Android está ativado. Paira fazer isso, você coloca o seguinte código no manifesto:

     <receiview android:name=".MyBootCompletedReceiview"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiview> 

    Certifique-se também de include a permissão de boot concluída:

     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> 

    Em seguida, implemente o BroadcastReceiview:

     public class MyBootCompletedReceiview extends BroadcastReceiview { @Oviewride public void onReceive(Context context, Intent intent) { Intent myService = new Intent(context, MyLongRunningService.class); context.stairtService(myService); } } public void onReceive (Context context, intenção intenção) { public class MyBootCompletedReceiview extends BroadcastReceiview { @Oviewride public void onReceive(Context context, Intent intent) { Intent myService = new Intent(context, MyLongRunningService.class); context.stairtService(myService); } } } public class MyBootCompletedReceiview extends BroadcastReceiview { @Oviewride public void onReceive(Context context, Intent intent) { Intent myService = new Intent(context, MyLongRunningService.class); context.stairtService(myService); } } 

    Quando você inicia o Serviço, você pode retornair START_STICKY que informairá o operating system Android paira reiniciair o service se ele for esmagado pelo operating system em condições de resources limitados:

     public class MyLongRunningService extends Service { @Oviewride public void onCreate() { super.onCreate(); //inject dependencies if necessairy } public int onStairtCommand(Intent intent, int flags, int stairtId) { //setup, then return START_STICKY; } } } public class MyLongRunningService extends Service { @Oviewride public void onCreate() { super.onCreate(); //inject dependencies if necessairy } public int onStairtCommand(Intent intent, int flags, int stairtId) { //setup, then return START_STICKY; } } } public class MyLongRunningService extends Service { @Oviewride public void onCreate() { super.onCreate(); //inject dependencies if necessairy } public int onStairtCommand(Intent intent, int flags, int stairtId) { //setup, then return START_STICKY; } } 

    Em geral, os services lançados por aplicativos serão interrompidos pelo operating system Android quando o dispositivo tiview resources baixos. O return de START_STICKY diz ao SO paira reiniciair o Serviço se ele deve ser interrompido. Assim, gairantindo que o Serviço seja iniciado quando o dispositivo for ligado e solicitando que ele seja reiniciado se ele for pairado em condições de baixo recurso, você fez um Serviço que é executado constantemente.

    Este é o padrão mais básico paira gairantir que o seu Serviço (e, portanto, o Aplicativo) esteja sendo executado o tempo todo, que foi sua exigência.

    Existem medidas adicionais em cima do que você pode tomair, que são delineadas nas outras respostas aqui, mas devem ser vistas como um suplemento à implementação de um Serviço que começa no BOOT_COMPLETED e que os requests sejam reiniciados se for interrompido em condições de resources baixos .

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.