简体   繁体   English

如何显示通知即使手机处于打盹或应用程序处于应用程序待机模式?

[英]How to show notifications EVEN when phone is in Doze or app is in App Standby mode?

I am building an app that should remind the user about upcoming events that they set (basically a reminder). 我正在构建一个应用程序,它应该提醒用户他们设置的即将发生的事件(基本上是提醒)。 The issue i'm running into is pushing notifications to the user's phone (only on API 26+) when the app has not been utilized for a while (about 15 minutes or more); 我正在遇到的问题是当应用程序暂时没有被使用(大约15分钟或更长时间)时,将通知推送到用户的手机(仅限API 26+); notifications are not displayed at all. 根本不显示通知。

I read up on this and realized that App Standby and Doze mode may prevent my app from pushing such notifications; 我读到了这一点并意识到App Standby和Doze模式可能会阻止我的应用程序推送此类通知; my notifications are received as intended by the user on phones running API 25 and below. 用户在运行API 25及更低版本的手机上按预期收到我的通知。 To solve this I tried using AlarmManager.setExactAndAllowWhileIdle() but the issue persists. 为了解决这个问题,我尝试使用AlarmManager.setExactAndAllowWhileIdle(),但问题仍然存在。

class TaskNotifications {
    private AlarmManager alarmManager;
    private Context c;

    TaskNotifications(Context context) {
        this.c = context;
        this.alarmManager = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
    }

    void setReminder(Context context, Task task) {
        if (VERSION.SDK_INT < Build.VERSION_CODES.O) {
            long reminderMilliseconds = task.getReminderMilliseconds();
            if (reminderMilliseconds > Calendar.getInstance().getTimeInMillis() && !task.isDone()) {
                Intent intent = new Intent(context, NotificationReceiver.class);
                intent.putExtra("ID", task.getID());
                intent.putExtra("TITLE", task.getTitle());
                intent.putExtra("DETAILS", task.getDetails());

                PendingIntent pendingIntent = PendingIntent.getBroadcast(context, task.getID(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
                if (VERSION.SDK_INT >= 23) {
                    this.alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, reminderMilliseconds, pendingIntent);
                } else
                    this.alarmManager.setExact(AlarmManager.RTC_WAKEUP, reminderMilliseconds, pendingIntent);
            }
        }
    }

    void cancelReminder(Task task) {
        if (VERSION.SDK_INT < Build.VERSION_CODES.O) {
            this.alarmManager.cancel(PendingIntent.getBroadcast(this.c, task.getID(),
                    new Intent(this.c, NotificationReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT));
        }
    }
}
public class NotificationReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent startIntent = new Intent(context, NotificationJobIntentService.class);

        startIntent.putExtra("ID", intent.getIntExtra("ID", -1));
        startIntent.putExtra("TITLE", intent.getStringExtra("TITLE"));
        startIntent.putExtra("DETAILS", intent.getStringExtra("DETAILS"));

        JobIntentService.enqueueWork(context, NotificationJobIntentService.class, intent.getIntExtra("ID", -1), startIntent);
    }
}
public class NotificationJobIntentService extends JobIntentService {
    private String CHANNEL_ID = getResources().getString(R.string.channel_name);

    protected void onHandleWork(@NonNull Intent intent) {
        createNotificationChannel(NotificationJobIntentService.this);

        int NOTIFICATION_ID = intent.getIntExtra("ID", -1);
        String GROUP = "NOTIFICATION_GROUP";

        String title = intent.getStringExtra("TITLE");
        if (title.isEmpty())
            title = getResources().getString(R.string.no_title);

        String details = intent.getStringExtra("DETAILS");
        if (details.isEmpty())
            details = getResources().getString(R.string.no_details);

        Intent openAppIntent = new Intent(NotificationJobIntentService.this, MainActivity.class);
        TaskStackBuilder create = TaskStackBuilder.create(this);
        create.addNextIntentWithParentStack(openAppIntent);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(NotificationJobIntentService.this, this.CHANNEL_ID)
                .setContentTitle(title)
                .setContentText(details)
                .setSmallIcon(R.drawable.baseline_alarm_black_18)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setContentIntent(create.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT))
                .setCategory(NotificationCompat.CATEGORY_ALARM)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setGroup(GROUP)
                .setAutoCancel(true)
                .setColor(Color.argb(100, 0, 87, 75))
                .setVibrate(new long[]{1000, 1000})
                .setLights(Color.GREEN, PathInterpolatorCompat.MAX_NUM_POINTS, PathInterpolatorCompat.MAX_NUM_POINTS)
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));

        NotificationManagerCompat.from(this).notify(NOTIFICATION_ID, builder.build());
    }

    private void createNotificationChannel(Context context) {
        if (VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence string = context.getString(R.string.channel_name);
            String description = context.getString(R.string.channel_description);
            NotificationChannel notificationChannel = new NotificationChannel(this.CHANNEL_ID, string, NotificationManager.IMPORTANCE_HIGH);
            notificationChannel.setDescription(description);
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.GREEN);
            notificationChannel.enableVibration(true);
            notificationChannel.setVibrationPattern(new long[]{1000, 1000});
            (context.getSystemService(NotificationManager.class)).createNotificationChannel(notificationChannel);
        }
    }
}

Is there a reliable way for me to send exact/somewhat exact notifications to my users' phones running API 26+? 有没有可靠的方法让我向运行API 26+的用户手机发送准确/稍微确切的通知? Or is there an error in my code that I did not notice? 或者我的代码中是否有错误,我没有注意到?

I was unable to make the notification system work on API 26+ devices, however, I used the Android Calendar Provider Reminders to add the event to the users calendar and then set a reminder through the default calendar...not what I originally wanted, but it is a band-aid solution. 我无法使通知系统在API 26+设备上运行,但是,我使用Android日历提供程序提醒将事件添加到用户日历,然后通过默认日历设置提醒...不是我原来想要的,但它是一种创可贴解决方案。

If anybody can still solve the problem as intended, please let me know. 如果有人仍能按预期解决问题,请告诉我。

Code below: 代码如下:

if (task.getEventID() > 0) {
                //Remove existing events for this task
                ContentResolver cr = c.getContentResolver();
                int iNumRowsDeleted;
                Uri eventUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, task.getEventID());
                iNumRowsDeleted = cr.delete(eventUri, null, null);
                Log.i("removeEvent()", "Deleted " + iNumRowsDeleted + " calendar entry.");
            }
            try {
                //Add an event
                ContentResolver cr = context.getContentResolver();
                ContentValues values = new ContentValues();
                values.put(CalendarContract.Events.DTSTART, task.getCal().getTimeInMillis());
                values.put(CalendarContract.Events.DTEND, task.getCal().getTimeInMillis()+60*60*1000);//Each task a duration of 60 minutes
                values.put(CalendarContract.Events.TITLE, task.getTitle() + " - " + task.getDetails());
                values.put(CalendarContract.Events.CALENDAR_ID, getPrimaryCalendar());
                values.put(CalendarContract.Events.EVENT_TIMEZONE, Calendar.getInstance().getTimeZone().getID());

                Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);

                // Save the eventId into the Task object for possible future delete.
                task.setEventID(Integer.parseInt(uri.getLastPathSegment()));
                Log.i("addEvent()","The event id is " + task.getEventID());

                // Add a reminder
                ContentValues valuesR = new ContentValues();
                valuesR.put(CalendarContract.Reminders.MINUTES, (task.getCal().getTimeInMillis() - reminderMilliseconds)/(1000*60));
                valuesR.put(CalendarContract.Reminders.EVENT_ID, task.getEventID());
                valuesR.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT); /*The alarm method, as set on the server. METHOD_DEFAULT, METHOD_ALERT, METHOD_EMAIL, METHOD_SMS and METHOD_ALARM are possible values; the device will only process METHOD_DEFAULT and METHOD_ALERT reminders (the other types are simply stored so we can send the same reminder info back to the server when we make changes).*/
                Uri uriR = cr.insert(CalendarContract.Reminders.CONTENT_URI, valuesR);
                Cursor c = CalendarContract.Reminders.query(cr, task.getEventID(), new String[]{CalendarContract.Reminders.MINUTES});
                if (c.moveToFirst()) {
                    Log.i("setReminder()",task.toString());
                    Log.i("setReminder()","calendar has reminder at " + c.getInt(c.getColumnIndex(CalendarContract.Reminders.MINUTES)));
                }
                c.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将数据持续发送到 Firebase 以避免打瞌睡和应用待机 - How to send data to Firebase continuously avoiding Doze and App Standby 如何在 Doze 模式下将应用列入白名单 Android 6.0 - How to WhiteList app in Doze mode Android 6.0 应用程序关闭时如何显示通知? - How i can Show notifications when app is close? 手机处于打盹模式时扫描蓝牙 LE 设备,不起作用。 打盹模式时不调用回调方法 - Scanning for Bluetooth LE devices when the phone is in doze mode, don't work. CallBack method dosn't called when doze mode Android/Java:即使未“主动”使用应用程序,如何向用户发送通知? - Android/Java: how to send notifications to user, even when app is not "actively" being used? 应用程序被杀死时如何停止接收通知? - How to stop receiving notifications when app is killed? 解锁手机时显示应用程序锁定模式对话框 - show app lock pattern dialog when unlocking the phone 应用程序在后台时的Android通知 - Android notifications when app is in background 应用关闭时的通知 - Notifications when the app is turned off 即使传递了数据有效负载,应用在后台时也不会收到Firebase通知 - Firebase Notifications not being received when app is in background even if data payload is passed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM