Android - Démarrer le service au démarrage

107

D'après tout ce que j'ai vu sur Stack Exchange et ailleurs, j'ai tout configuré correctement pour démarrer un IntentService au démarrage du système d'exploitation Android. Malheureusement, il ne démarre pas au démarrage et je n'obtiens aucune erreur. Peut-être que les experts peuvent vous aider ...

Manifeste:

<?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 pour le démarrage:

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

MISE À JOUR : J'ai essayé à peu près toutes les suggestions ci-dessous, et j'ai ajouté une journalisation telle que Log.v("BatteryLogger", "Got to onReceive, about to start service");le gestionnaire onReceive de StartupIntentReceiver, et rien n'est jamais enregistré. Il ne parvient même pas au BroadcastReceiver.

Je pense que je déploie l'APK et que je teste correctement, j'exécute simplement Debug dans Eclipse et la console dit qu'elle l'installe avec succès sur ma tablette Xoom à \ BatteryLogger \ bin \ BatteryLogger.apk. Ensuite, pour tester, je redémarre la tablette, puis regarde les journaux dans DDMS et vérifie les services en cours d'exécution dans les paramètres du système d'exploitation. Est-ce que tout cela semble correct ou est-ce que je manque quelque chose? Encore une fois, toute aide est très appréciée.

Gady
la source
1
quel problème vous rencontrez, n'obtenez-vous aucune interface utilisateur ..?
Lalit Poptani
1
Le service ne démarre jamais, c'est le problème.
Gady
comment savez-vous que votre service ne démarre pas, avez-vous imprimé les journaux ou quelque chose comme ça ..?
Lalit Poptani
1
Vous n'avez pas besoin de journaux pour voir qu'il ne fonctionne pas. Le système d'exploitation Android expose les services en cours d'exécution. Cependant, il serait sage d'utiliser la journalisation pour voir si une erreur se produit. J'imagine que cela se produit avant context.startService () si une erreur se produit.
Tony
1
J'ai ajouté Log.v("BatteryLogger", "Got to onReceive, about to start service");au gestionnaire onReceive, et il n'apparaît jamais dans les journaux. Donc l'auditeur échoue (?)
Gady

Réponses:

302

Eh bien, voici un exemple complet d'application AutoStart

Fichier 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 - Cela apparaîtra chaque fois que vous démarrez l'appareil après avoir exécuté une fois l'application.

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
la source
10
+1 pour un exemple complet. Peut-être que je devrais changer mon IntentService avec onHandleIntent en un simple service ancien
Gady
6
Cela l'a finalement résolu. Le problème était une combinaison de mon service étant un IntentService au lieu d'un ancien service et des erreurs dans le code de service. La rigueur de cette réponse et la connexion sous Android m'ont aidé à résoudre mes problèmes.
Gady
3
+1 pour l'exemple détaillé. Cela fonctionnerait-il également sans activité?
balas du
1
Le rappel onStart () est obsolète. Vous devez utiliser onStartCommand () à la place.
mmBs
1
@mmBs cette réponse a presque 5 ans, donc c'est évident
Lalit Poptani
3

Votre service est peut-être arrêté avant la fin en raison de la mise en veille de l'appareil après le démarrage. Vous devez d'abord obtenir un verrou de réveil. Heureusement, la bibliothèque de support nous donne une classe pour faire ceci:

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

puis, dans votre service, assurez-vous de libérer le verrou de réveil:

    @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'oubliez pas d'ajouter l'autorisation WAKE_LOCK:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
phreakhead
la source
1
J'ai le même problème. Ça vous dérange de m'aider? Merci! stackoverflow.com/questions/35373525/starting-my-service
Ruchir Baronia
2

La suite devrait fonctionner. J'ai vérifié. Peut-être que votre problème est ailleurs.

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
la source
Merci pour cela, mais cela n'a toujours pas fonctionné. Les journaux n'indiquent même pas qu'il parvient à StartupIntentReceiver. D'autres idées?
Gady
1
Votre code fonctionne-t-il dans l'émulateur? Pouvez-vous recevoir l'intention dans l'émulateur?
Vivek
J'ai testé dans l'émulateur et j'obtiens une erreur dans DDMS, mais il semble au moins que le service tente de démarrer, bien qu'aucune de mes Log()déclarations ne soit là et que le périphérique émulateur n'indique pas que mon service s'exécute dans les paramètres du système d'exploitation. Voici l'erreur dans DDMS: System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43)cela signifie-t-il que le problème est sur la ligne 43 de mon service BatteryLogger?
Gady
2

J'ai trouvé un moyen de faire fonctionner correctement votre application lorsque l'appareil redémarre, veuillez suivre les étapes ci-dessous pour réussir.

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

Cela demande la permission de ne pas avoir besoin de gérer l'économie de batterie pour cette application afin que vous puissiez exécuter en arrière-plan de manière stable.

Déclarez ce code dans onCreate () de la 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);
Huy TRAN
la source
1

Cela ressemble beaucoup au mien mais j'utilise le nom complet du package pour le récepteur:

<receiver android:name=".StartupIntentReceiver">

J'ai:

<receiver android:name="com.your.package.AutoStart"> 
ciscogambo
la source
Ouais, c'était un peu difficile de trier votre problème, alors mieux vaut poster un exemple Hello world.
Lalit Poptani
1

J'ai eu du succès sans le package complet, savez-vous où la chaîne d'appels est interrompue? Si vous déboguez avec Log()'s, à quel moment cela ne fonctionne-t-il plus?

Je pense que cela peut être dans votre IntentService, tout semble bien.

Phix
la source
J'ai ajouté Log.v("BatteryLogger", "Got to onReceive, about to start service");au gestionnaire onReceive, et il n'apparaît jamais dans les journaux. Donc l'auditeur échoue (?)
Gady
Qu'est-ce qui fait démarrer le récepteur de diffusion lorsque le téléphone est démarré? Merci!
Ruchir Baronia le
Garçon. Je n'ai pas touché à Android depuis quelques années. Désolé @Ruchir
Phix
0

Juste pour faciliter la recherche, comme mentionné dans les commentaires, cela n'est pas possible depuis 3.1 https://stackoverflow.com/a/19856367/6505257

MrKew
la source
Ce n'est pas vrai, comme indiqué par Think Twice Code Once dans la section commentaires de la même réponse.
Ricardo A.
Une explication plus détaillée pour soutenir mon argument: stackoverflow.com/questions/20441308/…
Ricardo A.
Cela fait très longtemps que je n'ai rien fait avec Android, mais vous avez raison, c'est possible. Aucun autre argument nécessaire. (Je modifierai la réponse)
MrKew