Android - Dienst beim Booten starten

107

Nach allem, was ich in Stack Exchange und anderswo gesehen habe, habe ich alles richtig eingerichtet, um einen IntentService beim Starten des Android-Betriebssystems zu starten. Leider startet es nicht beim Booten und ich erhalte keine Fehler. Vielleicht können die Experten helfen ...

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.phx.batterylogger"
  android:versionCode="1"
  android:versionName="1.0"
  android:installLocation="internalOnly">

<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <service android:name=".BatteryLogger"/>
    <receiver android:name=".StartupIntentReceiver">  
        <intent-filter>  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
</application>

</manifest>

BroadcastReceiver für den Start:

package com.phx.batterylogger;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartupIntentReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent serviceIntent = new Intent(context, BatteryLogger.class);
        context.startService(serviceIntent);
    }
}

UPDATE : Ich habe fast alle der folgenden Vorschläge ausprobiert und die Protokollierung hinzugefügt, z. B. Log.v("BatteryLogger", "Got to onReceive, about to start service");zum onReceive-Handler des StartupIntentReceiver, und es wird nie etwas protokolliert. Es schafft es also nicht einmal zum BroadcastReceiver.

Ich denke, ich stelle das APK bereit und teste es korrekt. Ich führe nur Debug in Eclipse aus und die Konsole meldet, dass es erfolgreich auf meinem Xoom-Tablet unter \ BatteryLogger \ bin \ BatteryLogger.apk installiert wurde. Zum Testen starte ich das Tablet neu und schaue mir dann die Protokolle in DDMS an und überprüfe die laufenden Dienste in den Betriebssystemeinstellungen. Klingt das alles richtig oder fehlt mir etwas? Auch hier wird jede Hilfe sehr geschätzt.

Gady
quelle
1
Welches Problem bekommst du, bekommst du keine Benutzeroberfläche?
Lalit Poptani
1
Der Service startet einfach nie, das ist das Problem.
Gady
Woher wissen Sie, dass Ihr Dienst nicht gestartet wird? Haben Sie die Protokolle gedruckt oder ähnliches?
Lalit Poptani
1
Sie benötigen keine Protokolle, um zu sehen, dass es nicht ausgeführt wird. Das Android-Betriebssystem macht laufende Dienste verfügbar. Es ist jedoch ratsam, die Protokollierung zu verwenden, um festzustellen, ob ein Fehler auftritt. Ich würde eine Vermutung wagen, dass es vor context.startService () passiert, wenn ein Fehler auftritt.
Tony
1
Ich Log.v("BatteryLogger", "Got to onReceive, about to start service");habe den onReceive-Handler hinzugefügt und er wird nie in den Protokollen angezeigt. Also der Hörer versagt (?)
Gady

Antworten:

301

Hier ist ein vollständiges Beispiel für eine AutoStart-Anwendung

AndroidManifest-Datei

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pack.saltriver" android:versionCode="1" android:versionName="1.0">

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

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <receiver android:name=".autostart">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <activity android:name=".hello"></activity>
        <service android:enabled="true" android:name=".service" />
    </application>
</manifest>

autostart.java

public class autostart extends BroadcastReceiver 
{
    public void onReceive(Context context, Intent arg1) 
    {
        Intent intent = new Intent(context,service.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent);
        } else {
            context.startService(intent);
        }
        Log.i("Autostart", "started");
    }
}

service.java

public class service extends Service
{
    private static final String TAG = "MyService";
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    public void onDestroy() {
        Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onDestroy");
    }

    @Override
    public void onStart(Intent intent, int startid)
    {
        Intent intents = new Intent(getBaseContext(),hello.class);
        intents.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intents);
        Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
        Log.d(TAG, "onStart");
    }
}

hello.java - Dies wird jedes Mal angezeigt, wenn Sie das Gerät starten, nachdem Sie die Anwendung einmal ausgeführt haben.

public class hello extends Activity 
{   
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Toast.makeText(getBaseContext(), "Hello........", Toast.LENGTH_LONG).show();
    }
}
Lalit Poptani
quelle
10
+1 für ein vollständiges Beispiel. Vielleicht sollte ich meinen IntentService mit onHandleIntent in einen einfachen alten Service ändern
Gady
6
Dies löste es letztendlich. Das Problem war eine Kombination aus meinem Dienst als IntentService anstelle eines einfachen alten Dienstes und Fehlern im Dienstcode. Die Gründlichkeit dieser Antwort und die Anmeldung bei Android haben mir geholfen, meine Probleme zu lösen.
Gady
3
+1 für das detaillierte Beispiel. Würde dies auch ohne Aktivität funktionieren?
Balas
1
Der Rückruf von onStart () ist veraltet. Sie sollten stattdessen onStartCommand () verwenden.
mmBs
1
@mmBs diese Antwort ist fast 5 Jahre alt, also ist es offensichtlich
Lalit Poptani
3

Ihr Dienst wird möglicherweise vor dem Abschluss heruntergefahren, da das Gerät nach dem Booten in den Ruhezustand wechselt. Sie müssen zuerst eine Wecksperre erhalten. 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:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Phreakhead
quelle
1
Ich habe das gleiche Problem. Hast du etwas dagegen, mir zu helfen? Vielen Dank! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia
2

Folgendes sollte funktionieren. Ich habe überprüft. Vielleicht liegt dein Problem woanders.

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("TAG", "MyReceiver");
        Intent serviceIntent = new Intent(context, Test1Service.class);
        context.startService(serviceIntent);
    }
}




public class Test1Service extends Service {
    /** Called when the activity is first created. */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("TAG", "Service created.");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("TAG", "Service started.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.d("TAG", "Service started.");
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}




<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0"
      android:installLocation="internalOnly">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BATTERY_STATS" 
    />
<!--        <activity android:name=".MyActivity">
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER"></category> 
            </intent-filter>
       </activity> -->
        <service android:name=".Test1Service" 
                  android:label="@string/app_name"
                  >
        </service>
        <receiver android:name=".MyReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED" /> 
            </intent-filter>  
        </receiver> 
    </application>
</manifest>
Vivek
quelle
Danke dafür, aber es hat immer noch nicht funktioniert. Protokolle zeigen nicht einmal, dass es zum StartupIntentReceiver gelangt. Irgendwelche anderen Ideen?
Gady
1
Funktioniert Ihr Code im Emulator? Können Sie Absichten im Emulator empfangen?
Vivek
Ich habe im Emulator getestet und erhalte eine Fehlermeldung in DDMS, aber es sieht so aus, als würde zumindest der Dienst versuchen zu starten, obwohl keine meiner Log()Anweisungen darin enthalten ist und das Emulatorgerät meinen Dienst nicht als in den Betriebssystemeinstellungen ausgeführt anzeigt. Hier ist der Fehler in DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Bedeutet das, dass das Problem in Zeile 43 meines BatteryLogger-Dienstes auftritt?
Gady
2

Ich habe eine Möglichkeit gefunden, Ihre Anwendung beim Neustart des Geräts ordnungsgemäß auszuführen. Führen Sie die folgenden Schritte aus, um erfolgreich zu sein.

AndroidManifest-Datei

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pack.saltriver" android:versionCode="1" android:versionName="1.0">
<uses-permission 
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".UIBootReceiver" android:enabled="true" 
    android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
     <service android:name=".class_Service" />
</application>

UIBootReceiver

public class UIBootReceiver extends BroadcastReceiver {

private static final String TAG = "UIBootReceiver";
@Override

    public void onReceive(Context context, Intent arg1)
    {
        Toast.makeText(context, "started", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(context,class_Service.class);
        context.startService(intent);
    }
  }

Hiermit wird um Erlaubnis gebeten, die Batteriesparleistung für diese App nicht verwalten zu müssen, damit Sie stabil im Hintergrund ausgeführt werden können.

Deklarieren Sie diesen Code in onCreate () der MainActivity-Klasse:

   Intent myIntent = new Intent();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        myIntent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        myIntent.setData(Uri.parse("package:" + 
   DeviceMovingSpeed.this.getPackageName()));
    }
    startActivity(myIntent);
Huy TRAN
quelle
1

Sieht mir sehr ähnlich, aber ich verwende den vollständigen Paketnamen für den Empfänger:

<receiver android:name=".StartupIntentReceiver">

Ich habe:

<receiver android:name="com.your.package.AutoStart"> 
Ciscogambo
quelle
Ja, es war ein bisschen, um Ihr Problem zu lösen, also veröffentlichen Sie besser ein Hallo-Welt-Beispiel.
Lalit Poptani
1

Ich hatte Erfolg ohne das vollständige Paket. Wissen Sie, wo die Anrufkette unterbrochen wird? Wenn Sie mit debuggenLog() 's , ab wann funktioniert es nicht mehr?

Ich denke, es kann in Ihrem IntentService sein, das alles sieht gut aus.

Phix
quelle
Ich Log.v("BatteryLogger", "Got to onReceive, about to start service");habe den onReceive-Handler hinzugefügt und er wird nie in den Protokollen angezeigt. Also der Hörer versagt (?)
Gady
Was bringt den Rundfunkempfänger zum Starten, wenn das Telefon gestartet wird? Vielen Dank!
Ruchir Baronia
Junge. Ich habe Android seit ein paar Jahren nicht mehr berührt. Leider @Ruchir
Phix
0

Um die Suche zu vereinfachen, ist dies , wie in den Kommentaren erwähnt, seit 3.1 https://stackoverflow.com/a/19856367/6505257 nicht mehr möglich

MrKew
quelle
Das ist nicht wahr, wie von Think Twice Code Once im Kommentarbereich derselben Antwort angegeben.
Ricardo A.
Eine detailliertere Erklärung, um mein Argument zu stützen: stackoverflow.com/questions/20441308/…
Ricardo A.
Es ist wirklich lange her, dass ich irgendetwas mit Android gemacht habe, aber Sie haben Recht, es ist möglich. Keine weiteren Argumente erforderlich. (Ich werde die Antwort bearbeiten)
MrKew