Устройство Huawei убивает мой приоритетный сервис, даже с решением dontkillmyapp.com - PullRequest
4 голосов
/ 04 июля 2019

Я занимаюсь разработкой приложения, которое в основном для отслеживания местоположения . При запуске он сохраняет местоположения и отправляет их на сервер.

Код работает уже около 5 лет без каких-либо изменений, без ошибок.

Он реализован с помощью простой службы переднего плана.

В последние месяцы я получал сообщения об ошибках, связанных с , сервис случайно останавливался на устройствах Huawei. Сначала я подумал, что это какой-то редкий / новый сбой на новых андроидах, но было нет журналы ошибок вообще в Fabric.

Я попробовал это на новом устройстве Huawei, и, к моему большому удивлению, это явление действительно существует. Устройства Huawei (с EMUI) действительно убивают службы переднего плана через пару минут.

Это действительно очень плохо для моего приложения, во-первых, пользователи хотят долгое время запускать это приложение для отслеживания, а во-вторых, последние месяцы сделали Huawei популярным выбором среди пользователей Android. Как и у 10% моей базы пользователей есть устройства Huawei.

Мне известно о https://dontkillmyapp.com/ Это отличный сайт для получения информации об этой проблеме.

Я попробовал их решение, которое, по сути, добавило к моей службе wakelock с определенным тегом, , чтобы EMUI Huawei его не убивал.

Я пробовал это следующим образом, , но мое тестовое устройство Huawei по-прежнему прерывает мой приоритетный сервис через несколько минут.

Код внутри моего сервиса:

Я в основном получаю пробуждение в обратном вызове службы onCreate.

 private void acquireLock() {

    if (wakeLock == null) {
        PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE);
        if (mgr != null) {

            if (Build.MANUFACTURER.toLowerCase().equals("huawei")) {
                lockTag = "LocationManagerService";
            }

            wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockTag);

            Log.i("MY_TAG", "tag:" + lockTag);
        }
    }
    if (wakeLock != null && !wakeLock.isHeld()) {
        wakeLock.acquire();
        //also tried with: wakeLock.acquire(1000*60*60*72); 3 days wakelock just in case.
        Log.i("MY_TAG", "wakeLock acquired!");
    }
}

@Override
public void onCreate() {
    acquireLock();
}

E D I T:

Уточнение: моя служба является приоритетной, с постоянным уведомлением. Он может хорошо работать в течение ДНЕЙ на других устройствах.

Пожалуйста, помогите, если можете,

Адам

Ответы [ 4 ]

2 голосов
/ 08 июля 2019

Это не относится к телефонам Huawei, это касается версии ОС Android.

С момента выпуска Android 26 (Oreo). Google решил установить жесткие ограничения на разрешения, а также некоторые разрешения не были предоставлены.

По сути, я хотел бы предложить вам больше узнать о Google Oreo и более поздних политиках разрешений.

У меня тоже была твоя проблема. Мое приложение отлично работает на Android ниже 26, но после этого я столкнулся с большой катастрофой и сейчас работаю над этим, чтобы справиться с этим для новых пользователей Android-версии.

наконец, вы должны адаптироваться к текущей политике Google, в противном случае вам нужно принять решение SHIFT + DELETE.

Редактировать

Уточнение: мой сервис является приоритетным, с постоянным уведомление. Он может хорошо работать в течение ДНЕЙ на других устройствах.

Как вы пояснили, жизненный цикл вашего приложения продолжается, когда приложение закрывается.

До Android.O Вы можете запустить службу на getApplicationContext.startService(YOUR_INTENT_SERVICE), но после Android.O, как указано в документации Google здесь вы должны использовать IntentService вместо Сервис . Вам следует enqueueWork В противном случае ваш сервис не будет запущен.

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

После того, как Сервисы Android.O находятся в белом списке , когда приложение открыто и взаимодействует с пользователем, в противном случае оно переходит в черный список и будет закрыто для освобождения ресурсов для распределения. другими высокоприоритетными приложениями.

Вот фрагмент кода, который поможет вам преодолеть проблему.

public class job extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {       
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (!isMyServiceRunning(this, YourService.class)) {
                YourService.enqueueWork(this, YourService.class, 1000, new Intent());
            }
        } else {
            if (!isMyServiceRunning(this, YourService.class)) {
                Intent service = new Intent(this, YourService.class);
                this.startService(service);
            }
        }
        ScheduledWork.scheduleJob(this);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        jobFinished(params, true);
        return false;
    }

Выше кода - запланированное задание , которое будет вызываться в минуту и ​​ повторно запланировано снова. Затем проверяет версию ОС и пытается start service или ввести ее в enqueueWork

0 голосов
/ 10 июля 2019

У меня была похожая проблема несколько месяцев назад, я потратил много времени на поиск решения, и, наконец, я нашел это (я не знаю, работает ли у вас, но это помогло мне).

Я реализовал в приложении, которое я разработал, сервис, который восстанавливает позицию пользователя каждую минуту, эта позиция сохраняется в базе данных sqlite устройства.Мне нужно, чтобы приложение работало всегда без прерываний.

На этапе тестирования я обнаружил, что некоторые устройства прерывали выполнение моего кода (как в вашем случае).

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

Это решение поможет мне:

@SuppressLint({"NewApi", "BatteryLife"})
private void checkOptimization() {
    String packageName = getApplicationContext().getPackageName();
    PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
    if (pm != null) {
        if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                Intent intent = new Intent();
                intent.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + ctx.getPackageName()));
                ctx.startActivity(intent);
        } else {
            new initialize().execute();
        }
    }
}

В основном я спрашиваю пользователя (Я не могу сделать это каким-либо иным способом), чтобы позволить моему приложению избежать оптимизации (этот код работает для Build.VERSION.SDK_INT> = 23)

0 голосов
/ 09 июля 2019

Я тестировал приведенный ниже код в huawei, и он работал. Может быть, вы можете использовать его в своем сервисе с уведомлением. Это может быть не идеально, хотя я все еще новичок в этом вопросе.

public class SensorService extends Service {
public int counter=0;
Context context;



public SensorService(Context applicationContext) {
    super();


    Log.i("HERE", "here I am!");
}

static PhoneCallListener phoneListener = null;
TelephonyManager telephonyManager;
public SensorService() {


}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    String CHANNEL_ID = "yourid";
    String CHANNEL_NAME = "yourchannel";
    NotificationChannel channel = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        channel = new NotificationChannel(CHANNEL_ID,
                CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
    }

    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (manager != null) {
            manager.createNotificationChannel(channel);
        }
    }



    Notification notification = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        notification = new Notification.Builder(this, CHANNEL_ID)
                .setContentTitle("title")
                .setContentText("text")

                .setAutoCancel(true)
                .build();
        this.startForeground(1,notification);
    }






    telephonyManager = (TelephonyManager) this
            .getSystemService(Context.TELEPHONY_SERVICE);



    if(phoneListener == null) {

        if (telephonyManager != null) {
            phoneListener = new PhoneCallListener();
            telephonyManager.listen(phoneListener,
                    PhoneStateListener.LISTEN_CALL_STATE);
        }
    }

    System.out.println("SERVICE");
    return START_STICKY;


}


@Override
public void onDestroy() {
    super.onDestroy();
    Log.i("EXIT", "ondestroy!");
    Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);

    sendBroadcast(broadcastIntent);




    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, SensorService.class));

    } else {
        context.startService(new Intent(context, SensorService.class));
    }


    Intent brcast = new Intent(this, AlarmReceiver.class);

    sendBroadcast(brcast);


}



@Nullable
@Override
public IBinder onBind(Intent intent) {
    context = getApplicationContext();
    return null;
}


}
0 голосов
/ 08 июля 2019

Я думаю, проблема в том, как вы обрабатываете сервисы в своем приложении.
Главное, чтобы в строке состояния работало уведомление , указывающее, что служба, связанная с вашим приложением, запущена, и конечный пользователь может прекратить работу службы, щелкнув уведомление.
Это комбинация услуги + уведомление + необходимые политики.
Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...