- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在开发一个 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 应用。就是这样,杀死应用程序的所有资源,包括 alarms
、boradcast receivers
和 services
。该应用程序在屏幕锁定后被完全杀死,因此不会收到 警报
并且通知不会按逻辑显示。为了避免这种情况,华为提供了一种将应用程序置于保护模式的方法,这意味着当锁屏时,这些 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/
我有一个静态类。 static class AppDirectory { public static string PACSTEMP = Path.Combine(Path.GetTempPa
我已经设置了一个启用了推送通知的 iOS 应用。 我可以将消息推送到应用程序,例如角标(Badge)计数工作并相应更新。 但我从未在锁屏或其他地方看到标准的推送通知弹出窗口,但手机会振动,因此消息会通
我们有一个带有 Web 应用程序和一堆 Windows 服务的系统,它们在做一些后台工作。 每当我们需要对系统进行更实质性的更改时,我们最终不得不发出 IIS 重置,然后手动重新启动所有相关的 Win
我有以下几行 John SMith: A Pedro Smith: B Jonathan B: A John B: B Luis Diaz: A Scarlet Diaz: B 我需要获得所有获得
我正在编写一个 Java 客户端(在 weblogic 10.3 上)来调用一个安全的网络服务。我已获得安装在 cacerts、DemoIdentity.jks 和 DemoTrust,jks 中的客
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎偏离主题,因为它缺乏足够的信息来诊断问题。 更详细地描述您的问题或 include a mini
我正在尝试调用void方法addToList,该方法将通过用户传递给它的两个字符串除外。我检查了dataSource类,以确保它确实接受了那些作为参数。问题是我在该方法调用上始终收到标识符>预期错误,
我的任务:使用scanner方法从一行数据中提取字符串、 float 和整数。 数据格式为: Random String, 240.5 51603 Another String, 41.6 59087
这个问题已经有答案了: What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? (25 个回答)
首先我实例化一个游戏状态 class GameState extends state{ ArrayList levels; int currentLevelID; public GameState()
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我有一个实现为单例的 Controller 对象,它有一个可以随时驱逐对象的缓存。当一个对象即将被删除时,我想通知任何使用此 Controller 的类,以便它们能够做出适当的响应。我对这种行为的第一
因此,我尝试跨集群发送消息,该消息将包含一个 User 对象,该对象是一个可序列化类。 当我发送 String 或 int 时,它工作正常,消息发送没有问题,并且集群上的所有 channel 都收到它
我试图创建的程序是一个基本游戏,用户输入网格大小,选择 block 接收增加分数的奖品、从分数中夺走分数的强盗或结束游戏的炸弹。我收到堆栈流错误,但我不明白为什么? 抱歉,代码量很大,我只是无法找到问
使用此代码我会得到什么ConcurrentModificationException?我有一个同步(监听器)锁。 private void notifyListeners(MediumRenditio
我想在捕获 DeadlineExceededError 后正确退出。我还剩下多少钱来清理? 例如, try: do_some_work() except DeadlineExceededError
我有 2 个 Intranet 站点: http://intranetv1/ http://intranetv2/ v1基于.NET 1.1,v2基于.NET 3.5 在 v1 上,我创建了一个网页,
我有一个在 Linux 3.12 上运行的 C 程序。该程序产生几个子进程。其中一个进程会生成一个线程,该线程运行一段时间然后终止。当该子进程运行时,它会执行 epoll_wait()。 epoll_
我能够将 APNS 集成到我的应用程序中。现在我想在用户点击它或用户在使用应用程序时收到通知时处理通知。我使用下面的代码在收到通知时显示警报对话框: func application(applicat
当我试图在浏览器上运行这段代码时,出现了以下错误。"错误响应错误代码:501消息:不支持的方法(“POST”)。错误码解释:501-服务器不支持该操作。" 浏览器控制台出现以下错误: "1.加载资源失
我是一名优秀的程序员,十分优秀!