Android: avvia il servizio all'avvio


107

Da tutto ciò che ho visto su Stack Exchange e altrove, ho tutto impostato correttamente per avviare un IntentService all'avvio del sistema operativo Android. Sfortunatamente non si avvia all'avvio e non ricevo alcun errore. Forse gli esperti possono aiutare ...

Manifesto:

<?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 per l'avvio:

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

AGGIORNAMENTO : ho provato quasi tutti i suggerimenti di seguito e ho aggiunto la registrazione come Log.v("BatteryLogger", "Got to onReceive, about to start service");al gestore onReceive di StartupIntentReceiver e non viene mai registrato nulla. Quindi non arriva nemmeno al BroadcastReceiver.

Penso di distribuire l'APK e testarlo correttamente, eseguendo solo Debug in Eclipse e la console dice che lo installa correttamente sul mio tablet Xoom in \ BatteryLogger \ bin \ BatteryLogger.apk. Quindi per testare, riavvio il tablet, quindi guardo i log in DDMS e controllo i servizi in esecuzione nelle impostazioni del sistema operativo. Sembra tutto corretto o mi sto perdendo qualcosa? Ancora una volta, qualsiasi aiuto è molto apprezzato.


1
che problema stai riscontrando, non stai ricevendo alcuna interfaccia utente ..?
Lalit Poptani

1
Il servizio non si avvia mai, questo è il problema.
Gady

come sei venuto a sapere che il tuo servizio non è stato avviato, hai stampato i log o qualcosa del genere ..?
Lalit Poptani

1
Non hai bisogno di log per vedere che non è in esecuzione. Il sistema operativo Android espone i servizi in esecuzione. Tuttavia, sarebbe opportuno utilizzare la registrazione per vedere se si sta verificando un errore. Vorrei azzardare una supposizione che accada prima di context.startService () se si verifica un errore.
Tony

1
Ho aggiunto Log.v("BatteryLogger", "Got to onReceive, about to start service");al gestore onReceive e non viene mai visualizzato nei log. Quindi l'ascoltatore sta fallendo (?)
Gady

Risposte:


302

Bene, ecco un esempio completo di un'applicazione AutoStart

File AndroidManifest

<?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 - Questo pop-up ogni volta che avvii il dispositivo dopo aver eseguito l'applicazione una volta.

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

10
+1 per un esempio completo. Forse dovrei cambiare il mio IntentService con onHandleIntent in un semplice vecchio servizio
Gady

6
Questo alla fine lo ha risolto. Il problema era una combinazione del mio servizio che era un IntentService invece del semplice vecchio Servizio ed errori nel codice del servizio. La completezza di questa risposta e l'accesso ad Android mi hanno aiutato a risolvere i miei problemi.
Gady

3
+1 per l'esempio dettagliato. Funzionerebbe anche senza un'attività?
balas

1
Il callback di onStart () è deprecato. Dovresti invece usare onStartCommand ().
mmBs

1
@mmBs questa risposta ha quasi 5 anni, quindi è ovvio
Lalit Poptani

3

Il servizio potrebbe essere interrotto prima del completamento a causa del dispositivo che va in stop dopo l'avvio. Devi prima ottenere un wakelock. Fortunatamente, la libreria di supporto ci offre una classe per farlo:

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

quindi, nel tuo Servizio, assicurati di rilasciare il wakelock:

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

Non dimenticare di aggiungere l'autorizzazione WAKE_LOCK:

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

1
Sto avendo lo stesso problema. Ti dispiace aiutarmi? Grazie! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia

2

Di seguito dovrebbe funzionare. Ho verificato Forse il tuo problema è da qualche altra parte.

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>

Grazie per questo, ma ancora non ha funzionato. I log non mostrano nemmeno che arriva a StartupIntentReceiver. Altre idee?
Gady

1
Il tuo codice funziona nell'emulatore? Riesci a ricevere l'intento nell'emulatore?
Vivek

Ho provato nell'emulatore e ricevo un errore in DDMS, ma sembra che almeno il servizio stia tentando di avviarsi, sebbene nessuna delle mie Log()istruzioni sia presente e il dispositivo dell'emulatore non mostri il mio servizio come in esecuzione nelle impostazioni del sistema operativo. Ecco l'errore in DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)Significa che il problema è sulla linea 43 del mio servizio BatteryLogger?
Gady

2

Ho trovato un modo per far funzionare correttamente la tua applicazione quando il dispositivo si riavvia, segui i passaggi seguenti per avere successo.

File AndroidManifest

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

Questo sta chiedendo il permesso di non dover gestire il risparmio della batteria per questa app in modo da poter eseguire in background in modo stabile.

Dichiara questo codice in onCreate () della classe MainActivity:

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

1

Sembra molto simile al mio ma uso il nome completo del pacchetto per il ricevitore:

<receiver android:name=".StartupIntentReceiver">

Io ho:

<receiver android:name="com.your.package.AutoStart"> 

Sì, è stato un po 'per risolvere il tuo problema, quindi è meglio pubblicare un esempio di Hello World.
Lalit Poptani

1

Ho avuto successo senza il pacchetto completo, sai dove viene interrotta la catena di chiamate? Se esegui il debug con Log()'s, a che punto non funziona più?

Penso che possa essere nel tuo IntentService, sembra tutto a posto.


Ho aggiunto Log.v("BatteryLogger", "Got to onReceive, about to start service");al gestore onReceive e non viene mai visualizzato nei log. Quindi l'ascoltatore sta fallendo (?)
Gady

Cosa fa partire il ricevitore di trasmissione all'avvio del telefono? Grazie!
Ruchir Baronia

Ragazzo. Non tocco Android da alcuni anni. Mi dispiace @Ruchir
Phix

0

Solo per rendere la ricerca più facile, come menzionato nei commenti, questo non è possibile dal 3.1 https://stackoverflow.com/a/19856367/6505257


Non è vero, come affermato da Think Twice Code Once nella sezione commenti della stessa risposta.
Ricardo A.

Una spiegazione più dettagliata per supportare la mia argomentazione: stackoverflow.com/questions/20441308/…
Ricardo A.

È passato davvero molto tempo da quando ho fatto qualcosa con Android, ma hai ragione, è possibile. Non sono necessari altri argomenti. (
Modificherò
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.