web-dev-qa-db-fra.com

Essayer de démarrer un service au démarrage sur Android

J'ai essayé de démarrer un service lorsqu'un appareil démarre sur Android, mais je ne parviens pas à le faire fonctionner. J'ai consulté un certain nombre de liens en ligne, mais aucun des codes ne fonctionne. Est-ce que j'oublie quelque chose?

AndroidManifest.xml

<receiver
    Android:name=".StartServiceAtBootReceiver"
    Android:enabled="true"
    Android:exported="false"
    Android:label="StartServiceAtBootReceiver" >
    <intent-filter>
        <action Android:name="Android.intent.action._BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<service
    Android:name="com.test.RunService"
    Android:enabled="true" />

BroadcastReceiver

public void onReceive(Context context, Intent intent) {
    if ("Android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
        Intent serviceLauncher = new Intent(context, RunService.class);
        context.startService(serviceLauncher);
        Log.v("TEST", "Service loaded at start");
    }
}
325
Alex

Les autres réponses sont bonnes, mais je pensais tout résumer en une réponse complète.

Vous avez besoin des éléments suivants dans votre fichier AndroidManifest.xml:

  1. Dans votre élément <manifest>:

    <uses-permission Android:name="Android.permission.RECEIVE_BOOT_COMPLETED" />
    
  2. Dans votre élément <application> (assurez-vous d'utiliser un nom de classe pleinement qualifié [ou relatif] pour votre BroadcastReceiver):

    <receiver Android:name="com.example.MyBroadcastReceiver">  
        <intent-filter>  
            <action Android:name="Android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>  
    </receiver>
    

    (Vous n'avez pas besoin des attributs Android:enabled, exported, etc.: les valeurs par défaut Android sont correctes.)

    Dans MyBroadcastReceiver.Java:

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

De la question initiale:

  • il n'est pas clair si l'élément <receiver> était dans l'élément <application>
  • il n'est pas clair si le nom de classe qualifié complet (ou relatif) correct pour le BroadcastReceiver a été spécifié
  • il y avait une faute de frappe dans le <intent-filter>
598
Timo Bruck

Comme information supplémentaire: BOOT_COMPLETE est envoyé aux applications avant que le stockage externe ne soit monté. Ainsi, si l'application est installée sur un stockage externe, elle ne recevra pas le message de diffusion BOOT_COMPLETE.

Plus de détails ici dans la section Les récepteurs de diffusion à l'écoute de "démarrage terminé"

83
inazaruk

Comment démarrer le service au démarrage de l'appareil (application autorun, etc.)

Pour la première: depuis la version Android 3.1+, vous ne recevez pas BOOT_COMPLETE si l'utilisateur n'a jamais démarré votre application au moins une fois ou que l'utilisateur n'a pas "fermé l'application". Cela a été fait pour empêcher les logiciels malveillants d’enregistrer automatiquement le service. Ce trou de sécurité a été fermé dans les nouvelles versions d'Android.

Solution:

Créer une application avec une activité. Lorsque l'utilisateur l'exécute une fois, l'application peut recevoir le message de diffusion BOOT_COMPLETE.

Pour le second: BOOT_COMPLETE est envoyé avant le stockage externe. Si l'application est installée sur un stockage externe, elle ne recevra pas le message de diffusion BOOT_COMPLETE.

Dans ce cas, il y a deux solutions:

  1. Installez votre application sur le stockage interne
  2. Installez une autre petite application dans la mémoire interne. Cette application reçoit BOOT_COMPLETE et exécute une deuxième application sur un stockage externe.

Si votre application est déjà installée dans la mémoire de stockage interne, le code ci-dessous peut vous aider à comprendre comment démarrer le service au démarrage de l'appareil.


Dans Manifest.xml

Autorisation:

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

Enregistrez votre destinataire BOOT_COMPLETED:

<receiver Android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action Android:name="Android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

Enregistrez votre service:

<service Android:name="org.yourapp.YourCoolService" />

Dans le récepteur OnBoot.Java:

public class OnBoot extends BroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
        // Create Intent
        Intent serviceIntent = new Intent(context, YourCoolService.class);
        // Start service
        context.startService(serviceIntent);

    }

 }

Pour HTC, vous devez peut-être aussi ajouter Manifest ce code si l'appareil n'intercepte pas RECEIVE_BOOT_COMPLETED:

<action Android:name="Android.intent.action.QUICKBOOT_POWERON" />

Receiver ressemble maintenant à ceci:

<receiver Android:name="org.yourapp.OnBoot">
    <intent-filter>
        <action Android:name="Android.intent.action.BOOT_COMPLETED"/>
        <action Android:name="Android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

Comment tester BOOT_COMPLETED sans redémarrer l'émulateur ou le périphérique réel? C'est facile. Essaye ça:

adb -s device-or-emulator-id Shell am broadcast -a Android.intent.action.BOOT_COMPLETED

Comment obtenir l'identifiant de l'appareil? Obtenir la liste des appareils connectés avec les identifiants:

adb devices

adb dans ADT par défaut, vous pouvez trouver dans:

adt-installation-dir/sdk/platform-tools

Prendre plaisir! )

66
user3439968

De même que

<action Android:name="Android.intent.action.BOOT_COMPLETED" />  

utiliser aussi,

<action Android:name="Android.intent.action.QUICKBOOT_POWERON" />

Les appareils HTC ne semblent pas attraper BOOT_COMPLETED

34
Tony

notez qu'au début de la question, il y a une faute de frappe:

<action Android:name="Android.intent.action._BOOT_COMPLETED"/>

au lieu de :

<action Android:name="Android.intent.action.BOOT_COMPLETED"/>

un petit "_" et tout ce problème :)

20
Evgeny Erlihman

Je viens de découvrir que c'était peut-être à cause de l'option Fast Boot dans Settings> Power

Lorsque cette option est désactivée, mon application reçoit cette diffusion, mais pas autrement.

En passant, j'ai Android 2.3.3 sur HTC Incredible S.

J'espère que ça aide.

13
Omer Akhter

Je pense que votre manifeste doit ajouter:

<uses-permission Android:name="Android.permission.RECEIVE_BOOT_COMPLETED" />
12
RickNotFred

Après avoir essayé toutes les réponses et astuces mentionnées, j'ai enfin trouvé pourquoi le code ne fonctionnait pas dans mon téléphone. Certains Android téléphones tels que "Huawei Honor 3C Android 4.2.2" ont un menu Statup Manager dans leurs paramètres et votre application doit être cochée dans la liste. . :)

6
Amir

J'ai une balise <category>- supplémentaire, je ne sais pas si cela fait une différence.

<receiver Android:name="BootIntentReceiver">  
        <intent-filter>  
            <action Android:name="Android.intent.action.BOOT_COMPLETED" />  
            <category Android:name="Android.intent.category.HOME" />  
        </intent-filter>  
</receiver>

Avez-vous essayé d'omettre la clause if "Android.intent.action.BOOT_COMPLETED".equals(intent.getAction(), car le destinataire ne reçoit probablement cette intention que de toute façon?

5
Nick

Référer ce lien http://khurramitdeveloper.blogspot.in/2013/06/start-activity-or-service-on-boot.html Procédure pas à pas pour utiliser le démarrage sur le service

4
Jaichander

Avant le montage du stockage externe, BOOT_COMPLETE est envoyé à execute. Si votre application est installée sur un stockage externe, elle ne recevra pas le message de diffusion BOOT_COMPLETE. Pour éviter cela, vous pouvez installer votre application dans la mémoire de stockage interne. vous pouvez le faire en ajoutant simplement cette ligne dans menifest.xml

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:installLocation="internalOnly"
... >

Certains appareils HTC peuvent activer une fonctionnalité de "démarrage rapide" qui s'apparente davantage à une hibernation profonde qu'à un véritable redémarrage et ne doit donc pas donner l'intention de BOOT_COMPLETE. Pour le récupérer, vous pouvez ajouter ce filtre d'intention dans votre récepteur:

            <intent-filter>
                <action Android:name="Android.intent.action.BOOT_COMPLETED" />
                <action Android:name="Android.intent.action.QUICKBOOT_POWERON" />
            </intent-filter>
3

Si vous utilisez Android Studio et que vous aimez très bien l'auto-complétion, je dois vous informer que j'utilise Android Studio v 1.1.0 et que j'ai utilisé l'auto-complétion. complète pour la permission suivante

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

Et Android Studio Auto-completedRECEIVE_BOOT_COMPLETED tous en minuscules comme receive_boot_completed et j'ai continué à me tirer les cheveux car j'avais déjà coché ma liste de contrôle pour commencer le service. au démarrage. Je viens de confirmer à nouveau

Android Studio NE complète automatiquement cette autorisation en minuscule.

2
Haroon Dilshad

C'est ce que j'ai fait

1. J'ai fait la classe de receveur

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //whatever you want to do on boot
       Intent serviceIntent = new Intent(context, YourService.class);
       context.startService(serviceIntent);
    }
}

2. dans le manifeste

<manifest...>
    <uses-permission Android:name="Android.permission.RECEIVE_BOOT_COMPLETED"/>
    <application...>
        <receiver Android:name=".BootReceiver" Android:enabled="true" Android:exported="false">
            <intent-filter>
                <action Android:name="Android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    ...

.et après TOUTES CE QU'IL FAUT "régler" le récepteur dans votre MainActivity, il se peut qu'il soit dans le onCreate

...
 final ComponentName onBootReceiver = new ComponentName(getApplication().getPackageName(), BootReceiver.class.getName());
        if(getPackageManager().getComponentEnabledSetting(onBootReceiver) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
        getPackageManager().setComponentEnabledSetting(onBootReceiver,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);
...

la dernière étape que j'ai apprise d'ApiDemos

2
San Juan

Comme @Damian a commenté, toutes les réponses dans ce fil le font mal. Si vous le faites manuellement de cette façon, votre service risquerait de s’arrêter au milieu de l’appareil en veille. Vous devez d'abord obtenir un verrou de réveil. Heureusement, le la bibliothèque de support 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 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 la permission WAKE_LOCK à votre mainfest:

<uses-permission Android:name="Android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission Android:name="Android.permission.WAKE_LOCK" />
2
phreakhead

En fait, ces problèmes me préoccupent il y a peu, et il est vraiment très facile à résoudre, vous ne faites rien de mal si vous configurez l'autorisation "Android.intent.action.BOOT_COMPLETED" et le filtre de filtrage d'intention.

Sachez que si vous sous Android 4.X, vous devez exécuter l'écouteur de diffusion avant de démarrer le service au démarrage, cela signifie que vous devez d'abord ajouter une activité, une fois que votre récepteur de diffusion est en cours d'exécution, votre application. devrait fonctionner comme prévu, cependant, sur Android 4.X, je n’ai pas trouvé le moyen de démarrer le service au démarrage sans aucune activité, je pense que Google l’a fait pour des raisons de sécurité.

1
David Hx

J'ai fait face à ce problème si je laisse le constructeur vide dans la classe du récepteur. Après la suppression du gestionnaire vide sur la réception, methos a commencé à fonctionner correctement.

0
redrom