Проблема с сохранением работоспособности приложения при блокировке телефона - PullRequest
0 голосов
/ 02 ноября 2018

Так что у меня раздражающая проблема. В настоящее время я работаю над приложением, которое используется для отслеживания сна пользователя. У нас есть служба, которая отправляет сонар и слушает возвращающиеся волны. Чтобы это работало, сервис должен работать всю ночь, а из-за некоторых других проблем нам нужен экран для блокировки. Эта служба запускается объектом, в который мы передаем интерфейс для обработки обратных вызовов, связанных с обработкой. В настоящее время вызывающая деятельность реализует этот интерфейс, чтобы правильно реагировать на обратные вызовы.

Теперь проблема, с которой я сталкиваюсь, иногда возникает во время сеанса мониторинга: либо служба уничтожается, либо приложение уничтожается. Чтобы исключить возможность быть убитым системой, я ищу стратегии, чтобы попытаться определить, какая система запущена и должна работать всю ночь, даже если экран заблокирован.

Сначала я попробовал активировать блокировку с помощью: PowerManager.PARTIAL_WAKE_LOCK

Я недавно добавил уведомление в трее, когда сеанс работает, чтобы попытаться сохранить его, но это не сработало так хорошо

public class Notification extends ContextWrapper {
    Context context;

    public Notification(Context base) {
        super(base);
        this.context = base;
        createChannels();
    }

    private NotificationManager mManager;

    public void createChannels() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel sessionChannel = new NotificationChannel(Constants.Notification.TRACKING_CHANNEL,
                    Constants.Notification.ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
            sessionChannel.enableLights(false);
            sessionChannel.enableVibration(false);
            getManager().createNotificationChannel(sessionChannel);
            NotificationChannel  bedtimeChannel = new NotificationChannel(Constants.Notification.BEDTIME_CHANNEL,
                    Constants.Notification.ANDROID_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
            getManager().createNotificationChannel(bedtimeChannel);

        }
    }

    public NotificationManager getManager() {
        if (mManager == null) {
            mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return mManager;
    }

    public NotificationCompat.Builder getTrackingChannelNotification(String title, String body) {
        Intent trackingIntent = new Intent(context, SessionRecordingActivity.class);
        trackingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, trackingIntent, 0);

        return new NotificationCompat.Builder(getApplicationContext(), Constants.Notification.TRACKING_CHANNEL)
                .setContentTitle(title)
                .setContentText(body)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setSmallIcon(R.mipmap.ic_launcher_new);
    }

    public NotificationCompat.Builder getBedTimeChannelNotification(String title, String body, Intent actionIntent) {
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, actionIntent, 0);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        return new NotificationCompat.Builder(getApplicationContext(), Constants.Notification.TRACKING_CHANNEL)
                .setSmallIcon(R.mipmap.ic_launcher_new)
                .setContentTitle(title)
                .setContentText(body)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(body))
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setContentIntent(pendingIntent)
                .setSound(defaultSoundUri)
                .setAutoCancel(true);
    }
}

Вот что я делаю после запуска службы:

NotificationCompat.Builder nb = mNotification.getTrackingChannelNotification(getString(R.string.tracking_in_progress), getString(R.string.sleep_well));
mNotification.getManager().notify(Constants.Notification.TRACKING_ID, nb.build());

А потом я делаю это, когда сессия заканчивается:

mNotification.getManager().cancel(Constants.Notification.TRACKING_ID);

Итак, на мой вопрос: что еще я могу сделать, чтобы указать системе, что мое приложение должно работать до тех пор, пока пользователь не завершит его? (Заметьте, что служба не запускается моим приложением напрямую, это сторонняя библиотека, запускающая службу).

РЕДАКТИРОВАТЬ: При дальнейшем расследовании теперь кажется, что может быть убита моя деятельность / приложение, а не служба. Существуют ли другие способы поддержания моего приложения в рабочем состоянии, когда экран блокируется, кроме блокировки пробуждения или уведомления в трее?

1 Ответ

0 голосов
/ 02 ноября 2018

Вы должны позвонить startForeground в Oncreate() для службы, которую вы используете Context.startForegroundService().

@Override
public void onCreate() {
    super.onCreate();

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        String CHANNEL_ID = "my_channel_01";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT);

        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();

        startForeground(1, notification);
    }
}

Вы можете узнать больше по этой ссылке

...