131 votes

Android - Démarrer le service au démarrage

D'après tout ce que j'ai vu sur Stack Exchange et ailleurs, j'ai tout configuré correctement pour lancer un IntentService au démarrage d'Android OS. Malheureusement, il ne démarre pas au démarrage, et je ne reçois aucune erreur. Peut-être les experts peuvent-ils m'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 Startup :

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 : 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"); au gestionnaire onReceive du StartupIntentReceiver, et rien n'est jamais enregistré. Donc ça n'arrive même pas jusqu'au BroadcastReceiver.

Je pense que je déploie l'APK et le teste correctement, je viens de lancer Debug dans Eclipse et la console indique qu'il l'installe avec succès sur ma tablette Xoom à l'adresse suivante \BatteryLogger\bin\BatteryLogger.apk. Ensuite, pour tester, je redémarre la tablette, puis je regarde les journaux dans DDMS et je 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 quelque chose m'échappe ? Encore une fois, toute aide est la bienvenue.

1 votes

Quel problème vous avez, vous n'avez pas d'interface utilisateur ?

1 votes

Le service ne démarre jamais, c'est ça le problème.

0 votes

Comment avez-vous su que votre service ne démarrait pas, avez-vous imprimé les journaux ou autre chose de ce genre ?

334voto

Prabuddha Points 37089

Eh bien, voici un exemple complet d'une 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 - Ce message apparaîtra chaque fois que vous démarrez l'appareil après avoir exécuté l'Applicaton une fois.

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

15 votes

+1 pour un exemple complet. Peut-être que je devrais changer mon IntentService avec onHandleIntent en un simple Service.

6 votes

Cela a finalement résolu le problème. Le problème était dû à la fois au fait que mon service était un IntentService et non un simple Service et à des erreurs dans le code du service. La rigueur de cette réponse et la connexion à Android m'ont aidé à résoudre mes problèmes.

3 votes

+1 pour l'exemple détaillé. Cela fonctionnerait-il aussi sans activité ?

4voto

Vivek Points 2064

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

Récepteur :

public class MyReceiver extends BroadcastReceiver{

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

Service :

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

Manifeste :

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

0 votes

Merci pour ça, mais ça ne marche toujours pas. Les journaux ne montrent même pas qu'il est parvenu au StartupIntentReceiver. D'autres idées ?

1 votes

Votre code fonctionne-t-il dans l'émulateur ? Pouvez-vous recevoir l'intention dans l'émulateur ?

0 votes

J'ai testé dans l'émulateur et j'obtiens une erreur dans le DDMS, mais il semble qu'au moins le service tente de démarrer, bien qu'aucune de mes fonctions de gestion de l'information ne soit disponible. Log() sont là et l'émulateur n'indique pas que mon service est en cours d'exécution dans les paramètres du système d'exploitation. Voici l'erreur dans le DDMS : System.err - at com.phx.batterylogger$1.onReceive(BatteryLogger.java:43) Cela signifie-t-il que le problème se situe à la ligne 43 de mon service BatteryLogger ?

3voto

phreakhead Points 2265

Il se peut que votre service s'arrête avant la fin de son exécution parce que l'appareil se met en veille après le démarrage. Vous devez d'abord obtenir un verrouillage de réveil. Heureusement, le La bibliothèque de soutien nous donne une classe pour le faire :

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

    @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 la permission WAKE_LOCK :

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

3voto

Huy TRAN Points 61

J'ai trouvé un moyen de faire en sorte que votre application fonctionne bien 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);
    }
  }

Il s'agit de demander la permission de ne pas avoir à gérer l'économie de la batterie pour cette application afin que vous puissiez fonctionner 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);

1voto

ciscogambo Points 766

Ressemble beaucoup à mine mais j'utilise le nom complet du paquet pour le récepteur :

<receiver android:name=".StartupIntentReceiver">

Je l'ai fait :

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

1 votes

Oui, c'était un peu difficile de résoudre votre problème, alors j'ai préféré poster un exemple de type "hello world".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X