Android - uruchamianie usługi w czasie rozruchu


109

Muszę uruchomić usługę w czasie rozruchu. Szukałem dużo. Mówią o Broadcastreceiver. Ponieważ jestem nowy w programowaniu dla Androida, nie mam jasnego obrazu usług na Androida. Proszę podać kod źródłowy.


25
@ user244540: Proszę nie „uruchamiać usługi w czasie rozruchu” z zamiarem ciągłego działania, chyba że stale dostarcza wartości (np. klient VOIP). W takich przypadkach użyj startForeground()w swojej usłudze. W przeciwnym razie Android i jego użytkownicy zabiją twoją usługę jako stratę miejsca, a ty otrzymasz nieprzyjemne komentarze w Android Market. W większości sytuacji, w których myślisz, że chcesz, aby usługa była uruchamiana w czasie rozruchu, lepiej jest korzystać z niej, AlarmManageraby usługa mogła działać okresowo, a nie w sposób ciągły .
CommonsWare

2
@CommonsWare: Słuszna uwaga. Należy jednak pamiętać, że aby rozpocząć okresowe przebiegi AlarmManagerpo ponownym uruchomieniu, należy wykonać bardzo podobne kroki (różnica polega na treści onReceivemetody)
standardowo

1
@CommonsWare: Bardzo dobry komentarz, natknąłem się na to pytanie, a Twoja wskazówka dokładnie pasuje do mojej sytuacji. Gdyby to była odpowiedź, zagłosowałbym za nią :-)
chiccodoro

Odpowiedzi:


95

Utwórz BroadcastReceiveri zarejestruj go, aby otrzymać ACTION_BOOT_COMPLETED . Potrzebujesz również uprawnienia RECEIVE_BOOT_COMPLETED .

Przeczytaj: Odsłuchiwanie i nadawanie globalnych wiadomości oraz ustawianie alarmów


2
a co z blokadą budzenia? podczas gdy usługa jest uruchamiany urządzenie może zdecydować, aby przejść śpi ...
Marian Paździoch

Czy muszę przynajmniej raz uruchomić telefon, aby rozpocząć usługę?
pathe.kiran

@ MarianPaździoch ma rację; potrzebujesz blokady budzenia. Zobacz moją odpowiedź poniżej: stackoverflow.com/a/30970167/473201
phreakhead


Twój ostatni adres URL jest nieaktualny
Prizoff

192

Twój odbiornik:

public class MyReceiver extends BroadcastReceiver {   

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

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

    }
}

Twój plik 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
Link do artykułu jest martwy, ale i tak przykładowy kod jest wszystkim, czego potrzebujesz, więc +1 :)
Alex

3
Właściwie wymaga to niewielkiej poprawy, musisz użyć wakelocka w odbiorniku, w przeciwnym razie istnieje niewielka szansa, że ​​twoja usługa się nie uruchomi.
Vladimir Ivanov

Czy muszę przynajmniej raz uruchomić telefon, aby to zadziałało?
pathe.kiran

1
Nie, ale musisz uruchomić aplikację co najmniej jedną od Androida 3.0
Vladimir Ivanov

Czy to działa, jeśli aplikacja jest wymuszana z poziomu ustawień? Czy aplikacja nadal będzie się wybudzać?
Srihari Karanth

32

Istnieje możliwość zarejestrowania własnej usługi aplikacji do automatycznego uruchamiania po uruchomieniu urządzenia. Jest to potrzebne na przykład, gdy chcesz odbierać zdarzenia push z serwera http i chcesz poinformować użytkownika, gdy tylko wystąpi nowe zdarzenie. Użytkownik nie musi uruchamiać aktywności ręcznie przed uruchomieniem usługi ...

To całkiem proste. Najpierw przyznaj swojej aplikacji uprawnienie RECEIVE_BOOT_COMPLETED. Następnie musisz zarejestrować BroadcastReveiver. Nazywamy to BootCompletedIntentReceiver.

Twój plik Manifest.xml powinien teraz wyglądać następująco:

<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>

Jako ostatni krok musisz zaimplementować odbiornik. Ten odbiornik właśnie uruchamia usługę w tle.

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);
  }
 }
}

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


3
Tak samo jak powyżej, ale naprawdę proste i szybkie, użyj tego, jeśli przyjdziesz przez ten post.
dbkoren,

Jedyną różnicą jest to, że deklaruje to usługę w Manifeście, co jest poprawne.
Joaquin Iurchuk

Zadeklarowanie służby w manifeście jest nie tylko poprawne, ale jest to wymagane. To samo co z zajęciami
Tim

Gdzie jest główna aktywność !? Tworzenie aplikacji bez aktywności lub android.intent.category.LAUNCHER!
nick

@ L'Esperanza na pewno możesz mieć aplikacje, które nie mają widocznych działań!
appsthatmatter

15

W większości przedstawionych tutaj rozwiązań brakuje ważnego elementu: zrobienie tego bez blokady uśpienia grozi śmiercią usługi przed zakończeniem przetwarzania. Widziałem to rozwiązanie w innym wątku, odpowiadając również tutaj.

Ponieważ WakefulBroadcastReceiver jest przestarzałe w API 26, jest zalecane dla poziomów API poniżej 26

Musisz uzyskać blokadę budzenia. Na szczęście biblioteka pomocy technicznej daje nam do tego klasę :

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);
    }
}

następnie w swojej usłudze pamiętaj o zwolnieniu blokady uśpienia:

    @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);
    }

Nie zapomnij dodać uprawnienia WAKE_LOCK i zarejestrować odbiorcę w manifeście:

<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
W pliku manifestu SimpleWakefulReceiver nie jest usługą.
Desmond Lua

1
WakefulBroadcastReceiver jest przestarzały
Amin Pinjari

5

powinieneś zarejestrować się w BOOT_COMPLETE, a także w 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
Literatura mówi, że „android.intent.action.REBOOT” może być używany tylko przez uprzywilejowaną aplikację / kod. Jaka to korzyść w przeciwnym razie?
XMAN

1

Zarejestruj również utworzoną usługę w Manifeście i pozwolenie na używanie jako

<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"/>

a potem w nowej obsadzie Reciever wezwać serwis

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

Dlaczego filtr intencji w usłudze?
Joaquin Iurchuk

ponieważ po zakończeniu rozruchu nazwa MyService zostanie nazwana
SoftEye

W takim przypadku klasa usług rozszerzy usługę i odbiornik transmisji. Czy mam rację?
Joaquin Iurchuk

Klasa rozszerzy klasę Service.
SoftEye

2
Coś tu jest nie tak. Usługa ma być wywoływana z Odbiornika transmisji. Ale mówisz, że twoja usługa jest odbiornikiem transmisji, a potem mówisz mi, że klasa usług nie rozszerza odbiornika transmisji. W związku z tym nie otrzyma komunikatu o zakończeniu rozruchu. Co nadpisujesz, deklarując metodę onReceive?
Joaquin Iurchuk

0

Najpierw zarejestruj odbiornik w pliku 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>

a następnie napisz transmisję dla tego odbiornika jak:

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

Aby ponownie uruchomić usługę w Android Olub więcej, tj. OS> 28 Użyj tego kodu WERSJA KOTLIN 1) Dodaj uprawnienia w manifeście

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

2) Utwórz Classi rozszerz go za pomocąBroadcastReceiver

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) Zadeklaruj w pliku manifestu w ten sposób pod znacznikiem aplikacji

<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

Sprawdź JobScheduler dla apis powyżej 26

WakeLock był najlepszą opcją do tego, ale jest przestarzały na poziomie API 26. Sprawdź ten link, jeśli rozważasz poziomy API powyżej 26
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

To mówi

Począwszy od Androida O, ograniczenia sprawdzania w tle sprawiają, że ta klasa nie jest już ogólnie użyteczna. (Generalnie nie jest bezpieczne uruchamianie usługi od momentu odebrania transmisji, ponieważ nie masz żadnych gwarancji, że Twoja aplikacja znajduje się w tym momencie na pierwszym planie, a zatem ma pozwolenie na to). Zamiast tego programiści powinni używać Androida. app.job.JobScheduler do zaplanowania zadania i nie wymaga, aby aplikacja utrzymywała w tym czasie blokadę wybudzenia (system zajmie się utrzymaniem blokady wybudzenia dla zadania).

tak jak mówi cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

jeśli ma coś zrobić, niż zacząć i to zatrzymać, możesz odebrać transmisję ACTION_BOOT_COMPLETED

Jeśli nie chodzi o pierwszy plan, sprawdź, czy usługa ułatwień dostępu może zrobić

inną opcją jest rozpoczęcie czynności z odbiornika rozgłoszeniowego i zakończenie jej po uruchomieniu usługi w ramach onCreate (), ponieważ nowsze wersje Androida nie pozwalają na uruchamianie usług z odbiorników

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.