База знаний
Автозапуск приложения при загрузке
Тема получения сообщения ACTION_BOOT_COMPLETED остается актуальной и по сей день. Многие новички сталкиваются с проблемой: они не получают в своих приложениях данное сообщение.
Можно выделить следующие правила:
В манифесте указать разрешение:
<uses-permission android:name=»android.permission.RECEIVE_BOOT_COMPLETED» />
В манифесте в блоке application зарегистрировать приёмник на приём сообщения ACTION_BOOT_COMPLETED:
<receiver android:name=».MyBroadcastReceiver»>
<intent-filter>
<action android:name=»android.intent.action.BOOT_COMPLETED» />
</intent-filter>
</receiver>
В описании без необходимости не указывайте атрибуты «enabled», «exported» и т.д. Вполне достаточно настроек и атрибутов по умолчанию.
Код вашего широковещательного приёмника:
public class BootCompletedReceiver extends BroadcastReceiver {
public BootCompletedReceiver() {
}
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
// ваш код здесь
}
}
}
Если ваш приёмник используется только для сообщения ACTION_BOOT_COMPLETED, то проверка «if» не обязательна. Однако иногда разработчики используют один и тот же ресивер для разных сообщений. В этом случае фильтруйте сообщения, проверяя их внутри метода onReceive().
Приложение должно быть установлено на внутреннюю память. Android устроена таким образом, что сообщение ACTION_BOOT_COMPLETED отправляется приложениям перед монтированием внешний памяти. Поэтому приложения, установленные на внешней памяти, никогда не получат это сообщение. Чтобы указать системе не устанавливать приложение на внешнюю память, в манифесте НЕ нужно прописывать для атрибута «@android:installLocation» значения «auto» или «preferExternal». По умолчанию, т.е. если этот атрибут не указан, Android установит ваше приложение только на внутреннюю память. Однако согласно официальной документации лучше явно указать значение «internalOnly», чтобы у вас и других разработчиков не возникло искушение в будущем указать иное значение.
<manifest xmlns:android=»http://schemas.android.com/apk/res/android»
android:installLocation=»internalOnly»
… >
После установки или принудительной остановки (force stop) приложение должно быть запущено хотя бы один раз, чтобы система «запомнила» это приложение для отправки ему сообщения ACTION_BOOT_COMPLETED. Такое поведение было реализовано в версии Android 3.1 в целях безопасности. В чем суть? Все только что установленные приложения находятся в состоянии «stopped» (не путать с активити, т.к. система управляет этим состоянием у приложений и активностей по-разному). В это же состояние приложение «уходит», когда пользователь в настройках телефона принудительно его останавливает. Пока приложение находится в таком состоянии, оно не будет запущено системой ни по какой причине (например, через ACTION_BOOT_COMPLETED), исключая, конечно же, запуск самим пользователем. Благодаря такому нововведению немалая часть вирусов и троянцев» перестала работать, т.к. уже нет возможности запуститься автоматом после установки.
Исключение составляют системные приложения.
Особенности режима Fast boot в HTC-устройствах: Известно, что HTC-устройства не перезагружаются в классическом смысле, а используют так называемый режим Fast boot (это одна из форм гибернации), сохраняя состояние ОС на диск. Поэтому сообщение ACTION_BOOT_COMPLETED не отправляется системой, т.к. в действительности перезагрузка не происходит. Вместо ACTION_BOOT_COMPLETED система может отправить следующие сообщения:
<action android:name=»android.intent.action.QUICKBOOT_POWERON» />
<action android:name=»com.htc.intent.action.QUICKBOOT_POWERON» />
В вашем приложении укажите в теге «receiver» кроме ACTION_BOOT_COMPLETED также вышеуказанные сообщения. Кроме этого необходимо прописать дополнительное разрешение:
<uses-permission android:name=»android.permission.QUICKBOOT_POWERON» />
Разберём ошибки, которые совершают новички при настройке приложения и в коде.
Toast toast = Toast.makeText(context.getApplicationContext(),
context.getResources().getString(R.string.your_message), Toast.LENGTH_LONG);
toast.show();
<receiver
android:name=».BootCompletedReceiver»
android:enabled=»true»
android:exported=»true» >
<uses-permission android:name=»android.permission.RECEIVE_BOOT_COMPLETED» />
<intent-filter>
<action android:name=»android.intent.action.BOOT_COMPLETED» />
</intent-filter>
</receiver>
В терминале выполните:
adb shell
Далее, чтобы отправить ACTION_BOOT_COMPLETED всем приложениям, наберите в терминале:
am broadcast -a android.intent.action.BOOT_COMPLETED
Или для отправки ACTION_BOOT_COMPLETED конкретному приложению наберите в терминале:
am broadcast -a android.intent.action.BOOT_COMPLETED your.package.name
В эмуляторе: установите ваше ПО, запустив его из студии. При этом студия соберет ваш проект, установит приложение и запустит его. После этого закройте эмулятор (это аналогично выключению на реальном устройстве). Чтобы получить сообщение ACTION_BOOT_COMPLETED, запустите эмулятор из AVD-менеджера, а не с помощью кнопки «Run app» в студии.
После запуска эмулятора во вкладке Android Monitor укажите запущенный эмулятор и ваше приложение, чтобы просмотреть логи logcat.
Чтобы ваше приложение запускалось при загрузке на всех устройствах, манифест как минимум должен выглядеть так:
<?xml version=»1.0″ encoding=»utf-8″?>
<manifest xmlns:android=»http://schemas.android.com/apk/res/android»
android:installLocation=»internalOnly»
package=»com.site.yourapp» >
<uses-permission android:name=»android.permission.RECEIVE_BOOT_COMPLETED» />
<uses-permission android:name=»android.permission.QUICKBOOT_POWERON» />
<application>
<activity
android:name=».MainActivity»
android:label=»@string/app_name» >
<intent-filter>
<action android:name=»android.intent.action.MAIN» />
<category android:name=»android.intent.category.LAUNCHER» />
</intent-filter>
</activity>
<receiver
android:name=».BootCompletedReceiver» >
<intent-filter>
<action android:name=»android.intent.action.BOOT_COMPLETED» />
<action android:name=»android.intent.action.QUICKBOOT_POWERON» />
<action android:name=»com.htc.intent.action.QUICKBOOT_POWERON» />
</intent-filter>
</receiver>
</application>
</manifest>
Код ресивера, как правило, будет таким:
public class BootCompletedReceiver extends BroadcastReceiver {
public BootCompletedReceiver() {
}
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast toast = Toast.makeText(context.getApplicationContext(),
context.getResources().getString(R.string.your_message), Toast.LENGTH_LONG);
toast.show();
Log.d(«myapp», context.getResources().getString(R.string.your_message);
// ваш код здесь
}
}
}