Android 本地通知不适用于三星 Galaxy

Posted

技术标签:

【中文标题】Android 本地通知不适用于三星 Galaxy【英文标题】:Android local notifications not working for samsung galaxy 【发布时间】:2019-02-10 07:07:54 【问题描述】:

长期以来,我一直在为 android 上复杂的本地通知而苦苦挣扎。

我有一个事件列表。用户可以选择何时收到通知:

活动当天 活动开始前一天 活动开始前两天

他/她还可以设置他/她想要得到通知的时间。每一次都是可能的。他/她也只能收到不同类型事件的通知。

实际情况是,它适用于除三星 Galaxy 手机之外的所有设备。用户告诉我,他们只会收到一次通知(当他们设置它们时),然后再也不会收到了。

我几乎尝试了所有方法,但我的想法已经不多了。三星似乎在通知方面存在一些问题,但它适用于其他一些应用程序。那么他们的代码和我的有什么区别。

也许其他人知道这个问题并且可以帮助我。这太棒了!

我的代码来了:

public int setEventNotifications(List<Event> chosenEvents) 

    SharedPreferences settings = context.getSharedPreferences(Constants.PREFS_EVENT_SETTINGS, 0);

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    ArrayList<PendingIntent> intentArray = new ArrayList<>();

    // To cancel an existing pending intent you need to recreate the exact same and cancel it -__-
    // So pending intents need to be stored in the database
    deleteOldGarbagePendingIntents();

    // get notification settings from shared prefs

    int hours = 0;
    int minutes = 0;

    String time = settings.getString(Constants.PREFS_EVENT_TIME, "00:00");
    String parts[] = time.split(":");

    try 
        hours = Integer.parseInt(parts[0]);
        minutes = Integer.parseInt(parts[1]);
     catch (Exception e) 
        Log.e(TAG, "Invalid time. Cannot be parsed: " + time);
    

    String interval = settings.getString(Constants.PREFS_EVENT_INTERVAL, "");

    String communeId = settings.getString(Constants.PREFS_EVENT_COMMUNE_ID, "");
    String regionId = settings.getString(Constants.PREFS_EVENT_REGION_ID, "");

    for (Event event : chosenEvents) 
        // check if date is in the future

        Intent intent = new Intent(context, AlarmGarbageReceiver.class);
        intent.putExtra("request_code", Integer.parseInt(event.getId()));
        intent.putExtra("event_type", event.getGarbageType().getType());
        intent.putExtra("event_date", event.getPickupDateAsDate().getTime());

        // calculate trigger time
        long triggerTime = calculateTriggerTime(event.getPickupDateAsDate(), hours, minutes, interval);
        Calendar alarmCalendar = Calendar.getInstance();
        alarmCalendar.setTimeInMillis(triggerTime);

        try 
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, Integer.parseInt(event.getId()), intent, FLAG_UPDATE_CURRENT);

            if (alarmManager != null) 
                alarmManager.set(AlarmManager.RTC_WAKEUP, alarmCalendar.getTimeInMillis(), pendingIntent);
             else 
                Log.e(TAG, "Alarmmanager is null");
            

            intentArray.add(pendingIntent);

            // save intents in database
            dbHelper.insertEventData(event.getId(), event.getEventType().getType(), String.valueOf(event.getPickupDateAsDate().getTime()), event.getLocation(), event.getEventType().getColor(), communeId, regionId);
         catch (SecurityException securityException) 
            Log.e(TAG, "Security Exception");
            securityException.printStackTrace();
         catch (Exception exception) 
            Log.e(TAG, "Exception");
            exception.printStackTrace();
        
    

    return intentArray.size();

AlarmEventReceiver 类:

public class AlarmEventReceiver extends BroadcastReceiver 

private static final String NOTIFICATION_CHANNEL_NAME = "xxx_events";
private static final String NOTIFICATION_CHANNEL_ID = "xxx_events_1";

@Override
public void onReceive(Context context, Intent intent) 
    if(intent.getExtras() != null) 
        Log.e(TAG, AlarmEventReceiver.class.getSimpleName() + " request code: " + intent.getExtras().getInt("request_code"));
    

    int eventId = intent.getExtras().getInt("request_code");
    String eventType = intent.getExtras().getString("event_type");
    long pickupDate = intent.getExtras().getLong("event_date");

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(pickupDate);
    calendar.set(Calendar.HOUR, 6);
    calendar.set(Calendar.MINUTE, 0);

    long finalDate = calendar.getTimeInMillis();

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    NotificationCompat.Builder builder;

    Intent resultIntent = new Intent(context, EventCalendarActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(EventCalendarActivity.class);
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

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

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) 
        builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);

        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]100, 200, 300, 400, 500, 400, 300, 200, 400);

        if (notificationManager != null) 
            notificationManager.createNotificationChannel(notificationChannel);
         else 
            Log.e(TAG, "Notification Manager is NULL");
        

        if (eventType != null) 
            builder.setChannelId(NOTIFICATION_CHANNEL_ID)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .setContentTitle("Erinnerung")
                    .setContentText(eventType)
                    .setWhen(finalDate)
                    .setContentIntent(resultPendingIntent)
                    .setAutoCancel(false)
                    .setVibrate(new long[]100, 200, 300, 400, 500, 400, 300, 200, 400);
        
     else 
        builder = new NotificationCompat.Builder(context);
        builder.setContentTitle("Erinnerung")
                .setDefaults(Notification.DEFAULT_ALL)
                .setContentText(eventType)
                .setWhen(finalDate)
                .setContentIntent(resultPendingIntent)
                .setAutoCancel(false)
                .setVibrate(new long[]100, 200, 300, 400, 500, 400, 300, 200, 400)
                .setPriority(Notification.PRIORITY_DEFAULT);

    

    Notification notification = builder.build();
    if (notificationManager != null) 
        notificationManager.notify(eventId, notification);
     else 
        Log.e(TAG, "notificationManager is NULL");
    


我曾经有机会在三星手机上运行它,我想我记得由于手机无法更新通知而引发了某种 SecurityException。只有 500 个通知的容量,如果尝试更新它们,旧的不会被删除,但会创建新的。因此,您很快就会收到 500 个通知,这就是引发 SecurityException 的时候。但是我再也找不到这个的来源了......

【问题讨论】:

要取消PendingIntent,您不需要完全重新创建它。您需要创建一个 PendingIntent 对象,该对象具有相同的 requestCodesame Intent with extras 并带有标志 FLAG_NO_CREATE。如果这样的PendingIntent 不存在,则该对象将为空,并且仅当它为非空时才需要取消它。如果我误解了你并且你做了同样的事情,我很抱歉。 请把偶数课也分享一下,谢谢。 【参考方案1】:

我在三星设备上也遇到了类似的问题,这就是我所做的:

考虑一下:

 builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);

在上面一行中我们通过了NOTIFICATION_CHANNEL_ID

现在在后面的代码中也添加了这一点:

builder.setChannelId(NOTIFICATION_CHANNEL_ID)     // don't call this method

我们已经通过构造函数将通道 id 提供给了构建器,我们不需要再次传递它。删除builder.setChannelId(NOTIFICATION_CHANNEL_ID)。它也适用于三星设备。

【讨论】:

【参考方案2】:

工作正常,在Samsung Galaxy s7 edge上测试

fun showDownloadNotification() 
        try 
            // val selectedUri = Uri.parse(Environment.getExternalStorageState())
            val notiIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
            notiIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            //            startActivity(intent);
            val pendingIntent: PendingIntent = PendingIntent.getActivity(baseActivity, 0, notiIntent, PendingIntent.FLAG_CANCEL_CURRENT)
            val builder = NotificationCompat.Builder(baseActivity, "")
                    .setSmallIcon(notificationIcon)
                    .setContentTitle("Subject Topic downloaded")
                    .setContentText(fileName)
                    .setAutoCancel(true)
                    .setContentIntent(pendingIntent)
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            val notificationManager: NotificationManagerCompat = NotificationManagerCompat.from(baseActivity)

            // notificationId is a unique int for each notification that you must define
            notificationManager.notify(1, builder.build())
         catch (e: Exception) 
            // Log.e(FragmentActivity.TAG, "Notification $e")
        
    

可能会有所帮助!

【讨论】:

【参考方案3】:

我过去浏览过一个相关问题,它发生在 Galaxy Note 上,虽然我不确定它是否会有所帮助。

mNotificationManager.cancel(notificationId);
mNotificationManager.notify(++notificationId, notification);

每次必须创建新通知时,手动取消之前的通知,并且每次都更新 notificationID。

【讨论】:

以上是关于Android 本地通知不适用于三星 Galaxy的主要内容,如果未能解决你的问题,请参考以下文章

三星 Galaxy S3 Android 浏览器上的 Web 套接字?

Android phonegap 应用程序在三星 Galaxy 设备上存在 SQlite 和本地存储问题

React 本机通知图标不适用于三星

Android 应用无法在三星 Galaxy 应用上提交(如何包含三星 SDK?)

Android : 通知在 2.3.6 (Samsung Galaxy y) 上不起作用

react-native-push-notification - 本地通知不适用于 Android