Фоновые службы ограничены в Xiaomi и Oppo

Мы разрабатываем приложение с MQTT, работающим в службе переднего плана. Проблема в Xiaomi Redmi Note 7, сервис прекращает работу после того, как мы убиваем приложение, но на других брендах он работает нормально. Я не тестировал приложение на Oppo и Vivo, но, когда я искал, у них тоже есть проблемы. В onCreate методе службы я вызвал startForeground(NOTIFICATION_ID, notification), и мое объявление службы в манифесте выглядит следующим образом

<service
    android:name=".service.mqtt.MqttService"
    android:enabled="true"
    android:exported="false"
    android:foregroundServiceType="location" />

Я также изменил foregroundServiceType на connectedDevice|dataSync|mediaPlayback, добавил android:stopWithTask="false" и вернул START_STICKY в onStartCommand метод обслуживания, но все еще не работает.


person Behrad Ranjbar    schedule 22.12.2019    source источник
comment
Как убить приложение? смахнуть его с экрана из недавних приложений?   -  person frogatto    schedule 22.12.2019
comment
@frogatto да !!   -  person Behrad Ranjbar    schedule 23.12.2019
comment
Подсказка: то же самое происходит и с Vivo.   -  person Shafizadeh    schedule 23.12.2019
comment
Согласно документам Android, приложение, имеющее службу переднего плана, не должно быть убито, когда пользователь смахивает его с экрана из недавних приложений, или Android должен запустить его вскоре позже. Если поведение отличается на конкретном устройстве, я думаю, что это проблема конкретного поставщика, о которой следует сообщить в их систему отслеживания проблем. Тем не менее, чтобы обойти эту проблему, вы можете настроить периодическую задачу AlarmManager, чтобы проверять, запущена ли служба, и запускать ее, если это не так.   -  person frogatto    schedule 23.12.2019
comment
@frogatto Я пробовал это с помощью WorkManager. но рабочий не просыпается при убитом приложении!   -  person Behrad Ranjbar    schedule 23.12.2019
comment
@Shafizadeh Это правда!   -  person Behrad Ranjbar    schedule 23.12.2019
comment
@BehradRanjbar Итак, похоже, что устройство Xiaomi принудительно останавливает приложение. Согласно документации, в режиме принудительной остановки вам потребуется явное намерение для запуска вашего приложения. то есть ваше приложение не будет запускаться неявными намерениями.   -  person frogatto    schedule 23.12.2019
comment
@frogatto на самом деле я запустил это намерение Intent xiaomi = new Intent (). setComponent (new ComponentName (com.miui.securitycenter, com.miui.permcenter.autostart.AutoStartManagementActivity)); и перенаправил пользователя на страницу настроек и занес мое приложение в белый список.   -  person Behrad Ranjbar    schedule 23.12.2019


Ответы (1)


Наконец-то я нашел ответ здесь

private static final Intent[] POWERMANAGER_INTENTS = {
    new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
    new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
    new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity")),
    new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
    new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
    new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
    new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
    new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
    new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
    new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
    new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
    new Intent().setComponent(new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
    new Intent().setComponent(new ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
    new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity"))
};



for (Intent intent : POWERMANAGER_INTENTS)
    if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
            // show dialog to ask user action
        break;
}

edit: Также существует проблема с проверкой, включен ли у пользователя автозапуск или нет. Как я искал, в настоящее время доступных решений нет. Я сам разработал решение. Я создал воркера, который каждые 25 минут будет экономить системное время в настройках. Каждый раз, когда приложение открывается, я проверяю настройки, и если с сохраненного времени прошло более 30 минут, это означает, что работник не смог выполнить работу, поэтому, возможно, пользователь не включил автоматический запуск в последний раз и должен подскажите еще раз.

class BackgroundCheckWorker(val appContext: Context, val workerParams: WorkerParameters) :
Worker(appContext, workerParams), KoinComponent {


override fun doWork(): Result {
    val pref = appContext.getSharedPreferences(PermissionHandler.AUTO_START_PREF, Context.MODE_PRIVATE)
    val editor = pref.edit()
    editor.putString(AUTO_START_PREF_KEY, Calendar.getInstance().time.toString())
    editor.apply()
    return Result.success()
}
}

И в заставке я вызываю эту функцию:

fun requestUnrestrictedBackgroundService(context: Activity): Boolean {
            val pref = context.getSharedPreferences(AUTO_START_PREF, Context.MODE_PRIVATE)
            var updated = false
            val lastUpdate = pref.getString(AUTO_START_PREF_KEY, "")
            updated = if (lastUpdate == null || lastUpdate == "") {
                val editor = pref.edit()
                editor.putString(AUTO_START_PREF_KEY, Calendar.getInstance().time.toString())
                editor.apply()
                false
            } else lastUpdate != "" &&
                    DateUtil.minAgo(lastUpdate) <= 30
            if (!updated) {
                for (intent in POWERMANAGER_INTENTS)
                    if (context.packageManager.resolveActivity(
                            intent,
                            PackageManager.MATCH_DEFAULT_ONLY
                        ) != null
                    ) {
                            val dialog = AlertDialog.Builder(context)
                            dialog.setMessage("On this device you must allow us to run services in background")
                                .setPositiveButton("Yes") { paramDialogInterface, paramInt ->
                                    val editor = pref.edit()
                                    editor.putString(AUTO_START_PREF_KEY, Calendar.getInstance().time.toString())
                                    editor.apply()
                                    context.startActivityForResult(intent, 1234)
                                }
                                .setNegativeButton("Cancel") { paramDialogInterface, paramInt -> context.finish() }
                            dialog.show()
                            return false
                    }
            }
            return true
        }
person Behrad Ranjbar    schedule 31.12.2019