Android - Iniciando o serviço no momento da inicialização


109

Preciso iniciar um serviço no momento da inicialização. Eu procurei muito. Eles estão falando sobre Broadcastreceiver. Como sou novo no desenvolvimento do Android, não tive uma ideia clara sobre os serviços no Android. Forneça algum código-fonte.


25
@ user244540: Não "inicie um serviço no momento da inicialização" com a intenção de executá-lo para sempre, a menos que esteja continuamente entregando valor (por exemplo, um cliente VOIP). Nesses casos, use startForeground()em seu serviço. Caso contrário, o Android e seus usuários eliminarão seu serviço por considerá-lo uma perda de espaço e você receberá alguns comentários desagradáveis ​​no Android Market. Na maioria das situações em que você pensa que deseja que um serviço seja iniciado no momento da inicialização, é melhor usá- AlarmManagerlo para que seu serviço possa ser executado periodicamente, em vez de continuamente .
CommonsWare

2
@CommonsWare: Bom ponto. No entanto, observe que para iniciar execuções periódicas AlarmManagerapós a reinicialização, você precisa seguir etapas muito semelhantes (a diferença está no conteúdo do onReceivemétodo)
normalmente

1
@CommonsWare: Comentário muito bom, me deparei com essa pergunta e sua dica se encaixa perfeitamente na minha situação. Se fosse uma resposta eu teria votado :-)
chiccodoro

Respostas:


95

Crie um BroadcastReceivere registre-o para receber ACTION_BOOT_COMPLETED . Você também precisa da permissão RECEIVE_BOOT_COMPLETED .

Leia: Ouvir e transmitir mensagens globais e definir alarmes


2
e o wake lock? enquanto o serviço está sendo iniciado, o dispositivo pode decidir adormecer ...
Marian Paździoch

Preciso inicializar meu celular pelo menos uma vez para iniciar um serviço?
pathe.kiran de

@ MarianPaździoch está certo; você precisa de um wake lock. Veja minha resposta abaixo: stackoverflow.com/a/30970167/473201
phreakhead

@ pathe.kiran na inicialização, sim. Consulte commonsware.com/blog/2011/07/05/boot-completed-regression.html
Tim,

Seu URL mais recente está desatualizado
Prizoff

192

Seu receptor:

public class MyReceiver extends BroadcastReceiver {   

    @Override
    public void onReceive(Context context, Intent intent) {

     Intent myIntent = new Intent(context, YourService.class);
     context.startService(myIntent);

    }
}

Seu AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.broadcast.receiver.example"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">

        <activity android:name=".BR_Example"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
        <receiver android:name=".MyReceiver" android:enabled="true" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

    </application>

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

</manifest>

5
O link para o artigo está morto, mas o código de amostra é tudo de que você precisa, então +1 :)
Alex

3
Na verdade, pouco precisa ser melhorado, você deve usar wakelock no receiver, caso contrário, há uma pequena chance de seu serviço não iniciar.
Vladimir Ivanov

Preciso inicializar meu celular pelo menos uma vez para fazer isso funcionar?
pathe.kiran de

1
Não, mas você deve executar o aplicativo pelo menos um desde o android 3.0
Vladimir Ivanov

Isso funciona se o aplicativo for fechado a partir das configurações? O aplicativo ainda será ativado?
Srihari Karanth

32

É possível registrar seu próprio serviço de aplicativo para iniciar automaticamente quando o dispositivo for inicializado. Você precisa disso, por exemplo, quando deseja receber eventos push de um servidor http e deseja informar ao usuário assim que um novo evento ocorrer. O usuário não precisa iniciar a atividade manualmente antes de o serviço começar ...

É bem simples. Primeiro, dê ao seu aplicativo a permissão RECEIVE_BOOT_COMPLETED. Em seguida, você precisa registrar um BroadcastReveiver. Nós o chamamos de BootCompletedIntentReceiver.

Seu Manifest.xml agora deve ter a seguinte aparência:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.jjoe64">
 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 <application>
  <receiver android:name=".BootCompletedIntentReceiver">
   <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
   </intent-filter>
  </receiver>
  <service android:name=".BackgroundService"/>
 </application>
</manifest>

Como última etapa, você deve implementar o Receptor. Este receptor apenas inicia seu serviço de segundo plano.

package com.jjoe64;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.jjoe64.BackgroundService;

public class BootCompletedIntentReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
  if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
   Intent pushIntent = new Intent(context, BackgroundService.class);
   context.startService(pushIntent);
  }
 }
}

De http://www.jjoe64.com/2011/06/autostart-service-on-device-boot.html


3
O mesmo que o anterior, mas realmente simples e rápido, use este se você vier por este post.
dbkoren de

A única diferença é que este declara o Serviço no Manifesto, o que é correto.
Joaquin Iurchuk

Não é apenas correto declarar seu serviço no manifesto, ele é obrigatório. O mesmo que com as atividades
Tim,

Onde está a atividade principal !? Não é correto fazer app sem atividades ou android.intent.category.LAUNCHER!
nick

@ L'Esperanza com certeza, você pode ter aplicativos que não têm atividades visíveis!
appsthatmatter

15

A maioria das soluções postadas aqui está perdendo uma peça importante: fazer isso sem um wake lock corre o risco de seu serviço ser interrompido antes de terminar o processamento. Vi essa solução em outro tópico, respondendo aqui também.

Como WakefulBroadcastReceiver foi descontinuado no api 26, ele é recomendado para níveis de API abaixo de 26

Você precisa obter um wake lock. Felizmente, a biblioteca de suporte nos oferece uma classe para fazer isso:

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

em seguida, em seu serviço, certifique-se de liberar o wake lock:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

Não se esqueça de adicionar a permissão WAKE_LOCK e registrar seu receptor no manifesto:

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

...

<service android:name=".SimpleWakefulReceiver">
    <intent-filter>
        <action android:name="com.example.SimpleWakefulReceiver"/>
    </intent-filter>
</service>

1
No arquivo de manifesto, SimpleWakefulReceiver não é um serviço.
Desmond Lua

1
WakefulBroadcastReceiver foi descontinuado
Amin Pinjari

5

você deve se registrar para BOOT_COMPLETE e também para REBOOT

<receiver android:name=".Services.BootComplete">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
        </intent-filter>
    </receiver> 

2
A literatura diz que 'android.intent.action.REBOOT' só pode ser usado por aplicativo / código privilegiado. Que vantagem é essa de outra forma?
XMAN

1

Registre também o serviço criado no Manifesto e use a permissão como

<application ...>
   <service android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.example.MyBroadcastReciver"/>
        </intent-filter>
   </service>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

e, em seguida, em braod cast Receptor ligue para seu serviço

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent myIntent = new Intent(context, MyService.class);
        context.startService(myIntent);
    }
}

Por que o filtro de intenção dentro do serviço?
Joaquin Iurchuk

porque quando a inicialização for concluída, o MyService será chamado
SoftEye

Nesse caso, sua classe de serviço estenderá o serviço e o receptor de transmissão. Estou certo?
Joaquin Iurchuk

A aula vai estender a aula de serviço.
SoftEye

2
Há algo errado aqui. O serviço deve ser chamado a partir do receptor de transmissão. Mas você está dizendo que seu serviço é o broadcast receiver e depois disso me diz que a classe de serviço não estende o Broadcast Receiver. Assim, ele não receberá a Transmissão de Boot Concluído. O que você está substituindo ao declarar o método onReceive?
Joaquin Iurchuk,

0

Primeiro, registre um receptor em seu arquivo manifest.xml:

    <receiver android:name="com.mileagelog.service.Broadcast_PowerUp" >
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

e então escreva uma transmissão para este receptor como:

public class Broadcast_PowerUp extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
        Toast.makeText(context, "Service_PowerUp Started",
                Toast.LENGTH_LONG).show();


    } else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {



        Toast.makeText(context, "Service_PowerUp Stoped", Toast.LENGTH_LONG)
        .show();
    }
  }
}

0

Para reiniciar o serviço em Android Oou mais, por exemplo, SO> 28 Use este código KOTLIN VERSION 1) Adicionar permissão no manifesto

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

2) Crie um Classe amplie-o comBroadcastReceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat



class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, arg1: Intent?) {
        Log.d("BootCompletedReceiver", "starting service...")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, Intent(context, YourServiceClass::class.java))
        } else {
            context.startService(Intent(context, YourServiceClass::class.java))
        }
    }
}

3) Declare no arquivo de manifesto como este na tag do aplicativo

<receiver android:name=".utils.BootCompletedReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

-1

Por favor, verifique o JobScheduler para apis acima de 26

WakeLock era a melhor opção para isso, mas está obsoleto na API de nível 26. Verifique este link se você considerar os níveis de API acima de 26
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

Diz

A partir do Android O, as restrições de verificação de histórico tornam essa classe geralmente não útil. (Geralmente não é seguro iniciar um serviço a partir do recebimento de uma transmissão, porque você não tem nenhuma garantia de que seu aplicativo está em primeiro plano neste ponto e, portanto, pode fazê-lo.) Em vez disso, os desenvolvedores devem usar o Android. app.job.JobScheduler para agendar um job, e isso não exige que o aplicativo mantenha um wake lock ao fazer isso (o sistema cuidará de manter um wake lock para o trabalho).

então, como diz cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

se for para fazer algo além de começar e mantê-lo, você pode receber a transmissão ACTION_BOOT_COMPLETED

Se não for sobre o primeiro plano, verifique se um serviço de acessibilidade pode servir

outra opção é iniciar uma atividade do broadcast receiver e terminá-la após iniciar o serviço em onCreate (), uma vez que as versões mais recentes do Android não permitem iniciar serviços a partir de receptores

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.