Android-Startdienst beim Booten


109

Ich muss beim Booten einen Dienst starten. Ich habe viel gesucht. Sie sprechen über Broadcastreceiver. Da ich neu in der Android-Entwicklung bin, habe ich mir kein klares Bild über die Dienste auf Android gemacht. Bitte geben Sie einen Quellcode an.


25
@ user244540: Bitte starten Sie einen Dienst nicht zum Startzeitpunkt mit der Absicht, dass er für immer ausgeführt wird, es sei denn, er liefert kontinuierlich einen Wert (z. B. ein VOIP-Client). In diesen Fällen verwenden Sie startForeground()in Ihrem Dienst. Andernfalls beenden Android und seine Benutzer Ihren Dienst als Platzverschwendung, und Sie erhalten einige unangenehme Kommentare im Android Market. In den meisten Situationen, in denen Sie glauben, dass ein Dienst zum Startzeitpunkt gestartet werden soll, sollten Sie ihn besser bedienen, AlarmManagerdamit Ihr Dienst nicht kontinuierlich, sondern regelmäßig ausgeführt werden kann .
CommonsWare

2
@ CommonsWare: Guter Punkt. Beachten Sie jedoch, dass Sie, um periodische Läufe AlarmManagernach dem Neustart zu starten, sehr ähnliche Schritte onReceive
ausführen müssen

1
@CommonsWare: Sehr guter Kommentar, ich bin über diese Frage gestolpert und Ihr Hinweis passt genau zu meiner Situation. Wenn es eine Antwort wäre, hätte ich dafür gestimmt :-)
Chiccodoro

Antworten:


95

Erstellen Sie ein BroadcastReceiverund registrieren Sie es, um ACTION_BOOT_COMPLETED zu erhalten . Sie benötigen außerdem die Berechtigung RECEIVE_BOOT_COMPLETED .

Lesen Sie: Abhören und Senden globaler Nachrichten und Einstellen von Alarmen


2
Was ist mit Wake Lock? Während der Dienst gestartet wird, kann das Gerät entscheiden, einzuschlafen ...
Marian Paździoch

Muss ich mein Handy mindestens einmal starten, um einen Dienst zu starten?
pathe.kiran

@ MarianPaździoch ist richtig; Du brauchst ein Wake Lock. Siehe meine Antwort unten: stackoverflow.com/a/30970167/473201
phreakhead


Ihre neueste URL ist veraltet
Prizoff

192

Ihr Empfänger:

public class MyReceiver extends BroadcastReceiver {   

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

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

    }
}

Ihre 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
Der Link zum Artikel ist tot, aber der Beispielcode ist sowieso alles, was Sie brauchen, also +1 :)
Alex

3
Eigentlich muss es wenig verbessert werden, Sie müssen Wakelock im Empfänger verwenden, sonst besteht eine kleine Chance, dass Ihr Dienst nicht gestartet wird.
Vladimir Ivanov

Muss ich mein Handy mindestens einmal booten, damit dies funktioniert?
pathe.kiran

1
Nein, aber Sie müssen die Anwendung mindestens eine seit Android 3.0 ausführen
Vladimir Ivanov

Funktioniert dies, wenn die App aus den Einstellungen zwangsweise geschlossen wird? Wird die App noch aufwachen?
Srihari Karanth

32

Es ist möglich, Ihren eigenen Anwendungsdienst für den automatischen Start zu registrieren, wenn das Gerät gestartet wurde. Dies benötigen Sie beispielsweise, wenn Sie Push-Ereignisse von einem http-Server empfangen und den Benutzer informieren möchten, sobald ein neues Ereignis auftritt. Der Benutzer muss die Aktivität nicht manuell starten, bevor der Dienst gestartet wird ...

Es ist ganz einfach. Geben Sie Ihrer App zunächst die Berechtigung RECEIVE_BOOT_COMPLETED. Als nächstes müssen Sie einen BroadcastReveiver registrieren. Wir nennen es BootCompletedIntentReceiver.

Ihre Manifest.xml sollte nun folgendermaßen aussehen:

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

Als letzten Schritt müssen Sie den Empfänger implementieren. Dieser Empfänger startet gerade Ihren Hintergrunddienst.

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

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


3
Wie oben, aber sehr einfach und schnell, benutze dieses, wenn du durch diesen Beitrag kommst.
dbkoren

Der einzige Unterschied besteht darin, dass dies den Dienst im Manifest deklariert, was korrekt ist.
Joaquin Iurchuk

Es ist nicht nur richtig, Ihren Dienst im Manifest zu deklarieren, es ist auch erforderlich. Gleich wie bei Aktivitäten
Tim

Wo ist die Hauptaktivität? Es ist nicht richtig, App ohne Aktivitäten zu machen oder android.intent.category.LAUNCHER!
Nick

@ L'Esperanza sicher, Sie können Apps haben, die keine sichtbaren Aktivitäten haben!
Appsthatmatter

15

Bei den meisten der hier veröffentlichten Lösungen fehlt ein wichtiges Element: Wenn Sie ohne Wake-Lock arbeiten, besteht die Gefahr, dass Ihr Service vor Abschluss der Verarbeitung beendet wird. Ich habe diese Lösung in einem anderen Thread gesehen und auch hier geantwortet.

Da WakefulBroadcastReceiver in API 26 veraltet ist, wird es für API-Level unter 26 empfohlen

Sie benötigen eine Wecksperre. Glücklicherweise gibt uns die Support-Bibliothek eine Klasse , um dies zu tun:

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

Stellen Sie dann in Ihrem Dienst sicher, dass die Wecksperre aufgehoben wird:

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

Vergessen Sie nicht, die WAKE_LOCK-Berechtigung hinzuzufügen und Ihren Empfänger im Manifest zu registrieren:

<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
In der Manifestdatei ist SimpleWakefulReceiver kein Dienst.
Desmond Lua

1
WakefulBroadcastReceiver ist veraltet
Amin Pinjari

5

Sie sollten sich sowohl für BOOT_COMPLETE als auch für REBOOT registrieren

<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
In der Literatur heißt es, dass 'android.intent.action.REBOOT' nur von privilegierten Apps / Codes verwendet werden kann. Welchen Vorteil hat das sonst?
XMAN

1

Registrieren Sie Ihren erstellten Dienst auch im Manifest und verwenden Sie die Berechtigung als

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

und dann rufen Sie in Braod Cast Reciever Ihren Service an

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

Warum der Absichtsfilter innerhalb des Dienstes?
Joaquin Iurchuk

Denn wenn der Startvorgang abgeschlossen ist, wird der MyService aufgerufen
SoftEye

In diesem Fall erweitert Ihre Serviceklasse den Service- und Broadcast-Empfänger. Habe ich recht?
Joaquin Iurchuk

Die Klasse erweitert die Serviceklasse.
SoftEye

2
Da stimmt was nicht. Der Dienst soll vom Rundfunkempfänger aufgerufen werden. Aber Sie sagen, dass Ihr Dienst der Rundfunkempfänger ist, und danach sagen Sie mir, dass die Dienstklasse den Rundfunkempfänger nicht erweitert. Daher wird der Boot Completed Broadcast nicht empfangen. Was überschreiben Sie, wenn Sie die onReceive-Methode deklarieren?
Joaquin Iurchuk

0

Registrieren Sie zuerst einen Empfänger in Ihrer Datei 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>

und schreiben Sie dann eine Sendung für diesen Empfänger wie:

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

So starten Sie den Dienst in Android Ooder mehr neu, z. B. Betriebssystem> 28 Verwenden Sie diesen Code. KOTLIN VERSION 1) Fügen Sie die Berechtigung im Manifest hinzu

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

2) Erstellen Sie ein Classund erweitern Sie es mitBroadcastReceiver

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) Deklarieren Sie in der Manifest-Datei wie folgt unter dem Anwendungs-Tag

<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

Bitte überprüfen Sie JobScheduler auf Apis über 26

WakeLock war die beste Option dafür, aber es ist in API-Level 26 veraltet. Bitte überprüfen Sie diesen Link, wenn Sie API-Levels über 26 berücksichtigen
Https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

Es sagt

Ab Android O ist diese Klasse aufgrund von Einschränkungen bei der Hintergrundprüfung im Allgemeinen nicht mehr nützlich. (Es ist im Allgemeinen nicht sicher, einen Dienst ab dem Empfang einer Sendung zu starten, da Sie zu diesem Zeitpunkt keine Garantie dafür haben, dass Ihre App im Vordergrund steht und dies daher darf.) Stattdessen sollten Entwickler Android verwenden. app.job.JobScheduler, um einen Job zu planen, und dies erfordert nicht, dass die App währenddessen eine Wecksperre hält (das System sorgt dafür, dass eine Wecksperre für den Job gehalten wird).

so wie es heißt cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

Wenn Sie etwas anderes tun möchten, als es zu starten und beizubehalten, können Sie die Sendung ACTION_BOOT_COMPLETED empfangen

Wenn es nicht um den Vordergrund geht, prüfen Sie bitte, ob ein Eingabehilfedienst dies kann

Eine andere Möglichkeit besteht darin, eine Aktivität vom Broadcast-Empfänger aus zu starten und nach dem Starten des Dienstes in onCreate () zu beenden, da neuere Android-Versionen das Starten von Diensten von Empfängern nicht zulassen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.