AlarmManager не работает в службе переднего плана, когда приложение было убито - PullRequest
0 голосов
/ 05 октября 2018

Мое приложение должно отправлять уведомления в указанное время.Я написал сервис, который использует AlarmManager, приемник, который перезапускает его, если вы закрываете приложение.Служба перезапускается (как видно из журналов), но AlarmManager не работает (получатель не получает от него намерения), пока приложение закрыто.Я также пытался зарегистрировать получателя в коде службы - он все еще не работает (AlarmService - служба переднего плана. AlarmSetter - класс для установки сигналов тревоги. AlarmReceiver - получатель для отправки уведомлений (имеет журнал: намерение получено)

Манифестфайл:

    <?xml version="1.0" encoding="utf-8"?>
        <manifest
            xmlns:android="http://schemas.android.com/apk/res/android"
            package="net.ozero.drugsreminder"
            android:installLocation="internalOnly">

            <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
            <uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
            <uses-permission android:name="android.permission.VIBRATE" />

            <application
                android:name=".App"
                android:allowBackup="true"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:theme="@style/AppTheme"
                >

                <activity android:name=".activities.MainActivity">
                    <intent-filter>
                        <action android:name="android.intent.action.MAIN" />

                        <category android:name="android.intent.category.LAUNCHER" />
                    </intent-filter>
                </activity>
                <activity
                    android:name=".activities.AddPrescActivity"
                    android:label="@string/label_add_presc_activity"
                    android:parentActivityName=".activities.MainActivity"
                    android:theme="@style/ActionBarTheme"
                    android:windowSoftInputMode="stateHidden">
                    <intent-filter>
                        <action android:name="android.intent.action.VIEW" />

                        <category android:name="android.intent.category.DEFAULT" />
                    </intent-filter>
                </activity>
                <activity
                    android:name=".activities.AddDrugActivity"
                    android:label="@string/label_add_drug_activity"
                    android:parentActivityName=".activities.AddPrescActivity"
                    android:theme="@style/ActionBarTheme"
                    android:windowSoftInputMode="stateVisible">
                    <intent-filter>
                        <action android:name="android.intent.action.VIEW" />

                        <category android:name="android.intent.category.DEFAULT" />
                    </intent-filter>
                </activity>
                <activity android:name=".activities.AlarmActivity">
                    <intent-filter>
                        <action android:name="android.intent.action.VIEW" />

                        <category android:name="android.intent.category.DEFAULT" />
                    </intent-filter>
                </activity>

                <service
                    android:name=".services.AlarmService"
                    android:enabled="true"
                    android:exported="true" >
                    <intent-filter>
                        <action android:name="net.ozero.drugsreminder.services.AlarmService.MarkEvent" />
                        <action android:name="net.ozero.drugsreminder.services.AlarmService.SetLater" />
                    </intent-filter>
                </service>
                <receiver
                    android:name=".services.AlarmReceiver"
                    android:enabled="true"
                    android:exported="true">
                    <intent-filter>
                        <action android:name="net.ozero.drugsreminder.services.AlarmReceiver" />
                    </intent-filter>
                </receiver>
                <receiver
                    android:name=".services.RestartAlarmServiceReceiver"
                    android:enabled="true"
                    android:exported="true">
                </receiver>
                <receiver
                    android:name=".services.BootCompleteReceiver"
                    android:enabled="true"
                    android:exported="true">
                    <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>

AlarmService:

    package net.ozero.drugsreminder.services;

        import android.app.AlarmManager;
        import android.app.NotificationManager;
        import android.app.Service;
        import android.content.Intent;
        import android.os.IBinder;
        import android.util.Log;

        import net.ozero.drugsreminder.alarm.AlarmSetter;
        import net.ozero.drugsreminder.database.DBHelper;
        import net.ozero.drugsreminder.datastructure.Event;
        import net.ozero.drugsreminder.formatters.AlarmMessageBuilder;

        import java.util.List;

        import static net.ozero.drugsreminder.App.*;
        import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;

        /**TODO alarm repeating (bug) */
        public class AlarmService extends Service {

            public AlarmService() {
            }

            public DBHelper mDBHelper;
            public AlarmReceiver mAlarmReceiver;
            public AlarmManager mAlarmManager;

            @Override
            public int onStartCommand(Intent intent, int flags, int startId) {

                Log.i("AlarmService:", "on start");

        //        mAlarmReceiver = new AlarmReceiver();

                mDBHelper = new DBHelper(this);

                //set event is done
                if (isMarkAction(intent)) {
                    markEvent(intent);
                }

                //set event to alarm later
                if (isSetLaterAction(intent)) {
                    setEventLater(intent);
                }
                setAlarms();

                return START_STICKY;
            }

            @Override
            public IBinder onBind(Intent intent) {
                throw new UnsupportedOperationException("Not yet implemented");
            }

            @Override
            public void onTaskRemoved(Intent rootIntent) {
                Log.i("AlarmService:", "on removed");
                sendBroadcast(new Intent(this, RestartAlarmServiceReceiver.class));

                Log.i(getClass().getName(), "OnTaskRemoves: broadcast sent");

                super.onTaskRemoved(rootIntent);
            }

            private boolean isMarkAction(Intent intent) {
                return (
                        intent != null
                        && intent.getAction() != null
                        && intent.getAction().equals(ACTION_MARK_EVENT)
                );
            }

            private boolean isSetLaterAction(Intent intent) {
                return (
                        intent != null
                                && intent.getAction() != null
                                && intent.getAction().equals(ACTION_SET_LATER)
                );
            }

            private void setEventLater(Intent intent) {
                int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
                mDBHelper.setEventLater(id, ALARM_INTERVAL);
                NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                assert notificationManager != null;
                notificationManager.cancel(id);
                Log.i("AlarmService:", "event time set later : " + id);
            }

            private void markEvent(Intent intent) {
                int id = intent.getIntExtra(EXTRA_ALARM_ID, 0);
                mDBHelper.markEvent(id);
                NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                assert notificationManager != null;
                notificationManager.cancel(id);
                Log.i("AlarmService:", "event is marked, id : " + id);
            }

            private void setAlarms() {

                mDBHelper = new DBHelper(this);

                List<Event> events = mDBHelper.getActualEvents();

                Log.i("AlarmService:setAlarms:", "actual (not marked) events size:" + String.valueOf(events.size()));

                AlarmSetter alarmSetter = new AlarmSetter(this);
                AlarmMessageBuilder alarmMessageBuilder = new AlarmMessageBuilder(mDBHelper);

                for (Event event : events) {

                    long timeMillis = event.getReceptionDateTime().getTime();
                    String message = alarmMessageBuilder.getMessage(event);
                    int id = event.getId();

                    alarmSetter.setAlarm(timeMillis, message, id);
                }
            }

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

                Log.i(getClass().getName(), "onDestroy");
            }
        }

AlarmSetter:

    package net.ozero.drugsreminder.alarm;

        import android.app.AlarmManager;
        import android.app.PendingIntent;
        import android.content.Context;
        import android.content.Intent;
        import android.os.Build;
        import android.util.Log;

        import net.ozero.drugsreminder.services.AlarmReceiver;

        import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
        import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;

        public class AlarmSetter {

            //one minute timeout
            public static final long DEFAULT_ALARM_TIMEOUT = 60*1000L;

            private Context mContext;
            private AlarmManager mAlarmManager;

            public AlarmSetter(Context applicationContext) {
                mContext = applicationContext;
                mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
                Log.i("AlarmSetter:", "alarm manager:" + mAlarmManager);
            }

            //main method
            public void setAlarm(long timeMillis, String message, int id) {

                //creating intent for alarm message
                Intent intent = new Intent("net.ozero.drugsreminder.services.AlarmReceiver");
                intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
                intent.putExtra(EXTRA_ALARM_MESSAGE, message);
                intent.putExtra(EXTRA_ALARM_ID, id);

                //creating pending intent
                PendingIntent pendingIntent = PendingIntent.getBroadcast(
                        mContext.getApplicationContext(), id, intent, 0);

                //setting alarm
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mAlarmManager.setExactAndAllowWhileIdle(
                            AlarmManager.RTC_WAKEUP,
                            timeMillis,
                            pendingIntent
                    );
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    mAlarmManager.setExact(
                            AlarmManager.RTC_WAKEUP,
                            timeMillis,
                            pendingIntent
                    );
                } else {
                    mAlarmManager.set(
                            AlarmManager.RTC_WAKEUP,
                            timeMillis,
                            pendingIntent
                    );
                }

                Log.i("AlarmSetter:" , "alarm set");
            }

        }

AlarmReceiver:

    package net.ozero.drugsreminder.services;

        import android.content.BroadcastReceiver;
        import android.content.Context;
        import android.content.Intent;
        import android.util.Log;

        import net.ozero.drugsreminder.alarm.NotificationSetter;

        import static net.ozero.drugsreminder.App.EXTRA_ALARM_ID;
        import static net.ozero.drugsreminder.App.EXTRA_ALARM_MESSAGE;

        public class AlarmReceiver extends BroadcastReceiver {

            @Override
            public void onReceive(Context context, Intent intent) {

                Log.i("AlarmReceiver:", "notification received");

                String message = intent.getStringExtra(EXTRA_ALARM_MESSAGE);
                int id = intent.getIntExtra(EXTRA_ALARM_ID, 1);
                NotificationSetter notificationSetter = new NotificationSetter(context);
                notificationSetter.setNotification(message, id);
            }
        }

1 Ответ

0 голосов
/ 05 октября 2018

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

Это простой пример из http://www.vogella.com/tutorials/AndroidServices/article.html:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...