Android - Как включить функцию автозапуска программно на устройствах Xiaomi?
Я разрабатываю приложение для Android, в котором я хочу отображать Push-уведомления.
Он хорошо отображается на большинстве устройств, кроме телефонов Xiaomi (я использую Redmi Note 4). Проблема, которую я обнаружил, заключается в том, что из-за опции автозапуска, предоставляемой Xiomi, она будет отключена по умолчанию, и пользователю необходимо включить ее вручную.
Но мне интересно, что в некоторых приложениях для Android я видел включение этой опции без какого-либо взаимодействия с пользователем. Например: WhatsApp. Если я попробую переустановить WhatsApp и увижу опцию Автозапуск, она включена!
Я не могу убедить нашего клиента, сказав, что это особенность устройств, подобных Xiomi, поскольку он указывает на некоторые приложения, которые работают нормально, как в примере, который я упомянул выше.
Этот вопрос задавали некоторые другие люди
Добавить мое приложение в список приложений AutoStart в Android программно
Но я не мог видеть ответы на них и размещать здесь с надеждой, что кто-то будет иметь ответ для этого.
5 ответов
Функция автозапуска включится автоматически, когда вы загрузите приложение из playstore, если операционная система xiaomi захочет, чтобы приложения, такие как amazon,google IO и т. Д., Также не имели права на автозапуск. В этом случае вам нужно перейти в раздел Разрешения безопасности -> автозапуск -> затем включите автозапуск оттуда. Вы не можете сделать автозапуск приложения по коду, все, что вы можете сделать, это показать диалоговое окно, чтобы включить автозапуск, и перевести пользователя к операции автозапуска, но это не очень хороший вариант, так как вы не можете проверить, работает ли автозапуск. включено или нет. Это сделано Ми в MIUI8 для экономии батареи. Эта проблема была потрачена впустую мои 2 дня XD
Вы можете обратиться к статье
Для устройств xiaomi, oppo, vivo и т. Д. Параметр Включить автозапуск программно
String manufacturer = android.os.Build.MANUFACTURER;
try {
Intent intent = new Intent();
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
} else if ("oppo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
} else if ("vivo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
} else if ("Letv".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
} else if ("Honor".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
}
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
Немногие популярные приложения работают в фоновом режиме и не уничтожаются во время цикла очистки памяти (многие популярные OEM-производители настраивают ПЗУ стека для оптимизации заряда батареи / памяти), поскольку эти производители "занесены в белый список". Для вашего приложения вы можете внести его в белый список либо вручную (с помощью соответствующих "настроек" для устройств), либо прагматично, перенаправив пользователей на соответствующую страницу настроек, чтобы белый список приложения. Прагматично вы можете сделать, как показано ниже:
Добавьте ниже разрешения в файле манифеста приложения:`
<uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE"/> <uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT"/>`
Перенаправьте к настройке автозапуска:
if (Build.BRAND.equalsIgnoreCase("xiaomi")) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")); startActivity(intent); } else if (Build.MANUFACTURER.equalsIgnoreCase("oppo")) { try { Intent intent = new Intent(); intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"); startActivity(intent); } catch (Exception e) { try { Intent intent = new Intent(); intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity"); startActivity(intent); } catch (Exception ex) { try { Intent intent = new Intent(); intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity"); startActivity(intent); } catch (Exception exx) { } } } }
Справочник по автозапуску для других производителей оборудования
Я протестировал этот метод, и он сработал, но надежность все еще остается вопросом, поскольку системе требуется время (около 2 минут на устройствах PoccoF9 и Xiomi) для перезапуска прерванной службы.
Но, как пользователь, мы можем предотвратить уничтожение всех фоновых сервисов приложения, как показано ниже:
- Нажмите физическую клавишу Недавние приложения (левая боковая кнопка).
- Перетащите приложение один раз (выберите, удерживайте и сдвиньте его вниз), нажмите на значок замка (если замок находится в открытом состоянии), чтобы заблокировать приложение.
- Приложение будет переведено в состояние блокировки (даже если вы очистите фоновые процессы приложения путем очистки, приложение продолжит работу).
- Точно так же, если вы хотите удалить его из состояния блокировки, просто перетащите вниз еще раз, и символ блокировки исчезнет (очистка фонового процесса также очистит приложение от запуска).
Но, таким образом, статус блокировки приложения будет сброшен при перезагрузке на большинстве устройств.
РЕДАКТИРОВАТЬ: После изучения поведения (на RedmiS3 Xiomi, Android V6.0) службы Foreground вот анализ:
Даже после включения "Автозапуска" программно (через вмешательство пользователя, как описано выше) служба не перезапускалась всегда (служба перезапускалась только несколько раз, но в большинстве случаев это не происходило).
Кроме того, если я ищу "Автозапуск" в настройках устройства, я не вижу свое приложение там в списке Автозапуск. Похоже, выше метод только обеспечивает разрешение автозапуска, но не включает его, НЕ УВЕРЕН! И, если я добавлю свое приложение в список "Автозапуск" через настройки устройства, моя служба будет перезапущена (хотя это займет некоторое время).Перезапуск уничтоженной службы в обратном вызове onTaskRemoved() может быть другой опцией, но этот обратный вызов вызывается неожиданным образом, когда убивается служба. Этот обратный вызов выполняется только тогда, когда приложение было закрыто должным образом нажатием клавиши назад. Если мы свернули приложение (состояние паузы), этот обратный вызов никогда не будет вызываться при уничтожении службы. (Ищу причину)
Недавно я нашел другой способ, чтобы убитый сервис мог быть перезапущен через событие уведомления GCM. Я сомневаюсь, что погода GCM работает, когда приложение убито на устройствах или нет (мне нужно проверить это и проверить поведение). Но одно это точно: "Эти производители сделали жизнь программиста адом!).
Я знаю, что уже слишком поздно делиться ответом, но я вставлю здесь свои пять копеек, потому что это очень и очень важно. Я потратил свои 2 дня на выкапывание этой проблемы. Я пробовал все предложенные решения, представленные здесь, но ничего не работало. Ниже приведено решение, которое я реализовал в следующие шаги:
Шаг # 01 Создайте свой сервис переднего плана, как вы это делаете, и зарегистрируйте его соответствующим образом в манифесте. В качестве образца я делюсь образцом обслуживания.
class MyService : Service() {
private var wakeLock: PowerManager.WakeLock? = null
override fun onBind(intent: Intent): IBinder? {
Log.d(tag!!, "Some component want to bind with the service")
// We don't provide binding, so return null
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(tag!!, "onStartCommand executed with startId: $startId")
// by returning this we make sure the service is restarted if the system kills the service
return START_STICKY
}
override fun onCreate() {
super.onCreate()
Log.d(tag!!, "The service has been created".toUpperCase(Locale.ROOT))
startForeground(1, NotificationUtils.createNotification(this))
acquireLock()
}
override fun onDestroy() {
super.onDestroy()
Log.d(tag!!, "The service has been destroyed".toUpperCase(Locale.ROOT))
Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show()
}
override fun onTaskRemoved(rootIntent: Intent?) {
Log.d(tag!!, "onTaskRemoved")
val restartServiceIntent = Intent(applicationContext, this.javaClass)
restartServiceIntent.setPackage(packageName)
val restartServicePendingIntent = PendingIntent.getService(applicationContext, 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT)
val alarmService = applicationContext.getSystemService(ALARM_SERVICE) as AlarmManager
alarmService[AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000] = restartServicePendingIntent
super.onTaskRemoved(rootIntent)
}
@SuppressLint("WakelockTimeout")
private fun acquireLock() {
// we need this lock so our service gets not affected by Doze Mode
wakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyService::lock").apply {
acquire()
}
}
}
}
ПРИМЕЧАНИЕ. Я рассмотрел все возможные варианты использования для перезапуска службы в случае, если она будет убита ОС. Остается одно, если пользователь перезапустит мобильный телефон. Этот случай можно легко найти с помощью других ответов stackoverflow. В Broadcast нужно просто запустить Service.
Шаг #02 Оформите заявку и зарегистрируйтесь в манифесте. И добавьте ниже строку кода в свой класс приложения.
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
val receiver = ComponentName(this, MyService::class.java)
val pm = packageManager
pm.setComponentEnabledSetting(
receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
}
Здесь MyService — это имя компонента, и это может быть Service или Broadcast Receiver , который вы уже используете в своем приложении. В моем случае я пытаюсь использовать службу Android
Теперь пришло время зарегистрировать этот класс приложения в файле манифеста. Откройте файл манифеста и в теге приложения используйте имя свойства и поместите имя вашего класса приложения, которое было только что создано MyApplication .
Шаг #03 Третьего шага нет. Вы сделали. Вы просто устанавливаете apk, и таким образом служба не будет убита, даже если приложение будет убито. Я протестировал вышеуказанное решение на устройстве Vivo, и оно сработало.
ПРИМЕЧАНИЕ. В случае, если вышеуказанное решение не работает, проверьте файл манифеста для свойства allowBackup , если вы обнаружите это свойство в файле манифеста, просто удалите его и удалите приложение, а затем установите приложение, оно будет работать наверняка, а затем вы можете установить это свойство снова.
Насколько я знаю, WhatsApp занесен в белый список на автозапуске устройства Xiaomi. С этим ничего не поделаешь. Конечно, ваше приложение будет занесено в белый список Xiaomi, если оно в конечном итоге получит такую же популярность, как WhatsApp. Пока этого не произойдет, вы можете попросить пользователя активировать его вручную, показав функцию автозапуска примерно так:
try {
Intent intent = new Intent();
if ("xiaomi".equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
intent.setComponent(new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity"));
}
// context is your Context
List<ResolveInfo> list = context.getPackageManager()
.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
context.startActivity(intent);
}
} catch (Exception e) {
Log.d("PERMISSION", e.toString());
}
Обратите внимание, что я не тестировал код для текущего устройства Xiaomi.