Попытка запустить сервис при загрузке на 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");
}
}
16 ответов
Остальные ответы выглядят неплохо, но я подумал, что все это оберну в один полный ответ.
Вам нужно следующее в вашем 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>
В качестве дополнительной информации: BOOT_COMPLETE отправляется приложениям перед подключением внешнего хранилища. Таким образом, если приложение установлено во внешнее хранилище, оно не получит широковещательное сообщение BOOT_COMPLETE.
Подробнее здесь, в разделе Приемники вещания, слушающие "загрузка завершена"
Как запустить сервис при загрузке устройства (автозапуск приложения и т. Д.)
Для начала: начиная с версии 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 вам может понадобиться добавить этот код в манифест, если устройство не перехватывает 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
Наслаждайтесь!)
Вместе с
<action android:name="android.intent.action.BOOT_COMPLETED" />
также использовать,
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Устройства HTC, кажется, не ловят BOOT_COMPLETED
Обратите внимание, что в начале вопроса есть ошибка опечатки:
<action android:name="android.intent.action._BOOT_COMPLETED"/>
вместо:
<action android:name="android.intent.action.BOOT_COMPLETED"/>
одна маленькая "_" и все это беда:)
Я думаю, что ваш манифест должен добавить:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Я только сейчас узнал, что это может быть из-за Fast Boot
вариант в Settings
> Power
Когда у меня отключена эта опция, мое приложение получает эту трансляцию, но не иначе.
Кстати, у меня есть Android 2.3.3
на HTC Incredible S
,
Надеюсь, поможет.
Перепробовав все упомянутые ответы и хитрости, я наконец нашел, почему код не работает в моем телефоне. Некоторые телефоны Android, такие как "Huawei Honor 3C Android 4.2.2", имеют в своих настройках меню Statup Manager, и ваше приложение должно быть проверено в списке.:)
У меня есть дополнительный <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()
Как получатель, вероятно, только получает это намерение в любом случае?
Это то что я сделал
1. Я сделал класс приемника
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
Ссылка на эту ссылку http://khurramitdeveloper.blogspot.in/2013/06/start-activity-or-service-on-boot.html Пошаговая процедура использования загрузки на Сервисе
Перед монтированием внешнего хранилища отправляется BOOT_COMPLETE execute.Если ваше приложение установлено во внешнее хранилище, оно не получит широковещательное сообщение 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>
Если вы используете Android Studio и очень любите автозаполнение, я должен сообщить вам, что я использую Android Studio v 1.1.0 и использовал автозаполнение для получения следующего разрешения.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
И Android Studio Авто-завершеноRECEIVE_BOOT_COMPLETED
все в нижнем регистре, как receive_boot_completed
и я продолжал вырывать свои волосы, потому что я уже отмечал свой контрольный список для действий, чтобы начать обслуживание при загрузке. Я только что подтвердил еще раз
Android Studio автоматически заполняет это разрешение в нижнем регистре.
Как прокомментировал @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 на свой основной фестиваль:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
На самом деле, я попал в эту проблему не так давно, и это действительно очень легко исправить, вы на самом деле ничего не делаете неправильно, если вы настраиваете "android.intent.action.BOOT_COMPLETED"
разрешение и интент-фильтр.
Обратите внимание, что если вы работаете на Android 4.X, вам нужно запустить широковещательный приемник, прежде чем запускать службу при загрузке, это означает, что вы должны сначала добавить действие, как только ваш широковещательный приемник запустится, ваше приложение должно функционировать так, как вы ожидали, однако в Android 4.X я не нашел способа запустить службу при загрузке без какой-либо активности, я думаю, что Google сделал это по соображениям безопасности.
Я столкнулся с этой проблемой, если я оставлю пустой конструктор в классе получателя. После удаления пустого contsructor onRreceive методы начали работать нормально.