Попытка запуска службы при загрузке на Android

Я пытаюсь запустить службу, когда устройство загружается на Android, но я не могу заставить его работать. Я просмотрел несколько ссылок в Интернете, но ни один из них не работает. Я что-то забыл?

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

Спасибо

Ответ 1

Другие ответы выглядят неплохо, но я подумал, что я завершу все в один полный ответ.

В вашем файле AndroidManifest.xml вам нужно следующее:

  • В элементе <manifest>:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
  • В вашем элементе <application> (обязательно используйте полное/квалифицированное имя класса для BroadcastReceiver):

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

    (вам не нужны атрибуты android:enabled, exported и т.д.: правильные значения по умолчанию для Android)

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

Из исходного вопроса:

  • Неясно, был ли элемент <receiver> в элементе <application>
  • Неясно, было ли указано правильное полное (или относительное) имя класса для BroadcastReceiver
  • в <intent-filter> была опечатка

Ответ 2

В качестве дополнительной информации: BOOT_COMPLETE отправляется в приложения перед установкой внешнего хранилища. Поэтому, если приложение установлено на внешнее хранилище, оно не получит широковещательное сообщение BOOT_COMPLETE.

Подробнее здесь в разделе Широковещательные приемники, прослушивающие "boot completed"

Ответ 3

Как начать службу при загрузке устройства (приложение автозапуска и т.д.)

Для начала: начиная с версии Android 3.1+ вы не получаете BOOT_COMPLETE, если пользователь никогда не запускал ваше приложение хотя бы один раз или пользователь не закрывал приложение. Это было сделано для предотвращения автоматической регистрации вредоносного ПО. Это отверстие безопасности было закрыто в новых версиях Android.

Решение:

Создайте приложение с активностью. Когда пользователь запускает его, когда приложение может получать широковещательное сообщение BOOT_COMPLETE.

Для второго: BOOT_COMPLETE отправляется перед установкой внешнего хранилища. Если приложение установлено на внешнюю память, оно не получит широковещательное сообщение BOOT_COMPLETE.

В этом случае существует два решения:

  • Установите приложение во внутреннюю память
  • Установите еще одно небольшое приложение во внутреннюю память. Это приложение получает BOOT_COMPLETE и запускает второе приложение на внешнем хранилище.

Если ваше приложение уже установлено во внутреннем хранилище, тогда код ниже поможет вам понять, как запустить сервис при загрузке устройства.


В Manifest.xml

Разрешение:

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

Зарегистрируйте приемник BOOT_COMPLETED:

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

Зарегистрируйте свой сервис:

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

В приемнике 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);

    }

 }

Для HTC вам может понадобиться также добавить в Manifest этот код, если устройство не поймает RECEIVE_BOOT_COMPLETED:

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

Получатель теперь выглядит следующим образом:

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

Как проверить BOOT_COMPLETED без перезапуска эмулятора или реального устройства? Это легко. Попробуйте следующее:

adb -s device-or-emulator-id shell am broadcast -a android.intent.action.BOOT_COMPLETED

Как получить идентификатор устройства? Получить список подключенных устройств с идентификаторами:

adb devices

adb в ADT по умолчанию вы можете найти в:

adt-installation-dir/sdk/platform-tools

Наслаждайтесь! )

Ответ 4

Наряду с

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

также использовать

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

Устройства HTC не выглядят BOOT_COMPLETED

Ответ 5

Обратите внимание, что в начале вопроса есть ошибка опечатки:

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

вместо:

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

один маленький "_" и все эти проблемы:)

Ответ 6

Я узнал только сейчас, что это может быть из-за опции Fast Boot в Settings > Power

Когда у меня отключена эта опция, мое приложение получает эту трансляцию, но не иначе.

Кстати, у меня есть Android 2.3.3 на HTC Incredible S.

Надеюсь, что это поможет.

Ответ 7

Я думаю, что ваш манифест должен добавить:

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

Ответ 8

У меня есть дополнительный <category> -tag, не знаю, имеет ли это значение.

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

Пробовали ли вы использовать if-предложение "android.intent.action.BOOT_COMPLETED".equals(intent.getAction(), поскольку получатель, вероятно, только получает это намерение?

Ответ 9

После того, как вы попробуете все упомянутые ответы и трюки, я наконец выясню, почему код не работает в моем телефоне. Некоторые Android-телефоны, такие как "Huawei Honor 3C Android 4.2.2", имеют меню Statup Manager в своих настройках, и ваше приложение должно быть проверено в списке. :)

Ответ 11

Перед установкой внешнего хранилища BOOT_COMPLETE отправляется execute.if ваше приложение установлено во внешнюю память, оно не получит широковещательное сообщение BOOT_COMPLETE. Чтобы предотвратить это, вы можете установить приложение во внутреннюю память. вы можете сделать это, просто добавив эту строку в menifest.xml

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

Некоторые устройства HTC могут включить функцию "быстрой загрузки", которая больше похожа на глубокую спячку, а не на реальную перезагрузку и, следовательно, не должна давать намерения BOOT_COMPLETE. Чтобы восстановить это, вы можете добавить этот фильтр намерения в свой приемник:

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

Ответ 12

Если вы используете Android Studio, и вы очень любите автозаполнение, я должен сообщить вам, я использую Android Studio v 1.1.0, и я использовал автозаполнение для следующего разрешения

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

И Android Studio Auto-completed RECEIVE_BOOT_COMPLETED все в нижнем регистре, как RECEIVE_BOOT_COMPLETED, и я продолжал вытягивать свои волосы, потому что я уже выбрал свой контрольный список для того, чтобы что-то делать, чтобы начать сервис при загрузке. Я только что подтвердил

Android Studio делает автоматическое заполнение этого разрешения в нижнем регистре.

Ответ 13

На самом деле, я недавно попал в эту проблему, и это действительно очень легко исправить, вы фактически ничего не делаете неправильно, если вы настроите разрешение "android.intent.action.BOOT_COMPLETED" и фильтр намерений.

Обратите внимание, что если вы на Android 4.X, вам нужно запустить широковещательный прослушиватель, прежде чем запускать службу при загрузке, это значит, что вы должны сначала добавить активность, как только ваш широковещательный приемник будет работать, ваше приложение должно функционировать как вы ожидали, однако, что на Android 4.X я не нашел способ запустить службу при загрузке без какой-либо активности, я думаю, что Google сделал это по соображениям безопасности.

Ответ 14

Как заметил @Damian, все ответы в этом потоке делают это неправильно. Выполнение этого вручную может привести к тому, что ваша служба будет остановлена ​​посередине от устройства, которое будет спать. Сначала вам необходимо установить блокировку слежения. К счастью, Библиотека поддержки дает нам класс, чтобы сделать это:

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

то в вашей службе обязательно отпустите блокировку слежения:

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

Не забудьте добавить WAKE_LOCK permssion к вашему mainfest:

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

Ответ 15

Я столкнулся с этой проблемой, если я оставлю пустой конструктор в классе получателя. После удаления пустого конструктора onRreceive methos начал нормально работать.

Ответ 16

Это то, что я сделал

1. Я сделал класс Receiver

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. в манифесте

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

3. и после ВСЕХ, КОТОРЫЕ НЕОБХОДИМО "установить" ресивер в свой MainActivity, он может быть внутри 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);
...

последний стебель, который я узнал из ApiDemos