gpt4 book ai didi

android - Android 上未收到通知

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:12:21 27 4
gpt4 key购买 nike

我正在开发一个 android 应用程序,主要用途是在设定的时间显示通知(一些特定的日历应用程序)。主要的提示之一是用户不(总是)收到通知,我束手无策。

我们已经在模拟器上针对 Android 4.4、6、7.0、7.1、8.0、8.1 对以下代码进行了内部测试,并使用了大约 10 台真实设备(6 到 8.1),所有设备都按时收到了通知。即使在重新启动后,所有通知都会按时收到。

我们遇到的其中一件事是三星设备上的 SecurityException(> 500 个注册警报),我们之前曾因取消不当而触发过。看起来这不再是问题。

那么,这些丢失的通知可能是什么原因造成的?这是设备特定的设置,还是一个简单的错误?还是有其他因素在起作用?

这是我们使用的代码:

private void cancelAlarm(String notificationId, Class<? extends AbstractReceiver> receiverClass)
throws BroadcastException {
/*
* Create an intent that looks similar, to the one that was registered using add. Making sure the notification id in the action is the same. Now we can search for
* such an intent using the 'getService' method and cancel it.
*/
final Intent intent = new Intent(this.context, receiverClass);
intent.setAction(notificationId);

final PendingIntent pi = PendingIntent.getBroadcast(this.context, 0, intent, 0);
final AlarmManager am = getAlarmManager();

try {
am.cancel(pi);
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), e.getMessage());
throw new BroadcastException(e.getMessage());
}
}

private void addOrUpdateAlarm(...){
try {
cancelAlarm(notificationId, OurReceiver.class);
} catch (BroadcastException e) {
Log.e(AlarmHelper.class.getSimpleName(), "addOrUpdateAlarm: Can't cancel current alarm before reinserting.", e);
}

Intent intent = new Intent(this.context, receiverClass);
intent.setAction(notificationId);
// some intent.setExtra() calls.
PendingIntent sender = PendingIntent.getBroadcast(this.context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

/* Get the AlarmManager service */
final AlarmManager am = getAlarmManager();

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
am.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}else{
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
}

然后在 OurReceiver 中我们创建一个通知 channel :

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
// Configure the notification channel.
mChannel.setDescription(description);
mChannel.enableLights(true);
// Sets the notification light color for notifications posted to this
// channel, if the device supports this feature.
mChannel.setLightColor(Color.RED);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);
}

最后发送一个通知:

    PendingIntent pIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), intent, 0);

Notification n = new NotificationCompat.Builder(context, channel)
.setContentTitle(notificationTitle)
.setContentText(notificationSubText)
.setSmallIcon(R.drawable.logo)
.setContentIntent(pIntent)
.setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE)
.setAutoCancel(true).build();

NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0, n);

最佳答案

关于通知,我可以告诉你以下几点:

在开发了一个使用大量来自 AlarmManager 的 Alarms 的应用程序之后,我发现了很多关于一些冲突设备的事情。 (我没有尝试过 JobScheduler,但在大多数情况下这项技术也会失败)。

有一些制造商(众所周知,华为、小米、三星等)干扰了 AlarmManager 的生命周期。

华为和小米

华为在锁屏时默认关闭所有不 protected 应用。就是这样,杀死应用程序的所有资源,包括 alarmsboradcast receiversservices。该应用程序在屏幕锁定后被完全杀死,因此不会收到 警报 并且通知不会按逻辑显示。为了避免这种情况,华为提供了一种将应用程序置于保护模式的方法,这意味着当锁屏时,这些 protected 应用程序不会被杀死。然后, protected 应用程序仍然会收到警报广播接收器

三星

三星有一个“功能”(开发人员不需要的功能)与华为和小米设备“相同”,但略有不同。三星不会在锁定屏幕时杀死非 protected 应用程序,但是当应用程序在 3 天内未打开时。用户闲置 3 天后,应用程序像华为和小米一样被杀死,因此不会收到通知(警报)。三星还提供了一种方法来保护应用程序并避免这种情况。

结论

还有其他制造商具有相同的行为,但我不了解所有制造商。我可以告诉你华为、小米和三星是其中最著名的。

因此,首先尝试了解是否所有故障设备都是由这些相互冲突的制造商制造的。

然后,有一些方法可以让用户知道通知可能不会在此设备中触发,并邀请他们将您的应用程序作为 protected 应用程序。

以编程方式,您可以执行类似的操作 ( source ):

if("huawei".equalsIgnoreCase(android.os.Build.MANUFACTURER)) { 
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.huawei_headline).setMessage(R.string.huawei_text)
.setPositiveButton(R.string.go_to_protected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
startActivity(intent);
}
}).create().show();
}

你也可以对其他有冲突的制造商做同样的事情。这就是我在这些设备中处理这种情况的方式,在大多数情况下,通知效果很好。

希望这对您有所帮助。

关于android - Android 上未收到通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50151538/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com