关于推送push中notification的一点问题

         对于推送,一般的APP都会有这种功能,这是一种拉回用户,使其重新用我们APP增强用户粘性的一种方法,所以这也是一种很常见的功能。但是之前一直没注意 ,所以也忽略了一些问题,最近正好碰到了,记录下来,防止大家再次踩坑。

         因为最近的业务场景的需要,一个用户会在很短的时间内收到比较多的推送,但是在之前的应用中,其实这种业务场景不会那么多的。但是现在出现了,也出现了两个问题。那么出现的问题是什么呢?问题一:当收到多条推送时候,在通知栏里面后面的会覆盖前面的。问题二:解决问题一后,点击了通知栏里面的notification,我们会传递一些值到广播接收器中,但是发现后面的值依然是会覆盖前面的值。

        其实看了下代码中,关于发送notification部分的代码就只有如下几行:

    //接收服务端发送过来的自定义消息 (服务器里面必须不能有其他设置,只是设置EXTRA_MESSAGE就好,title、content等都不要)
    private void processCustomMessage(Context context,String message){
        final NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        Intent intent = new Intent(context, PushIntentRecever.class);
        PersonalMessageBean personalMessageBean = GsonUtils.getModel(message,PersonalMessageBean.class);
        intent.putExtra(ConstantValue.PARCELABLE_DATA,personalMessageBean);
        intent.setAction("xxx");//如果是以PendingIntent方式发送广播,action必须设置对
        //第四个参数如果不是FLAG_UPDATE_CURRENT,那么传递的参数可能会收不到;如果第二个参数每次不是唯一的,那么传递的参数会覆盖
        PendingIntent pi = PendingIntent.getBroadcast(context, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        int defaults = 0;
        defaults |= Notification.DEFAULT_SOUND;//系统提示音
        defaults |= Notification.DEFAULT_VIBRATE;//系统震动
        defaults |= Notification.DEFAULT_LIGHTS;//系统灯光
        builder.setContentIntent(pi)
                .setSmallIcon(R.mipmap.ic_launcher).setTicker(ResourcesUtil.getString(R.string.app_name)).setWhen(System.currentTimeMillis())
                .setOnlyAlertOnce(true).setAutoCancel(true).setContentTitle(ResourcesUtil.getString(R.string.app_name))
                .setContentText(personalMessageBean.getMessageContent()).setDefaults(defaults);
        Notification notification = builder.build();
        //第一个参数是消息的notification的id,如果相同的话,那么通知就会覆盖啦
        nm.notify((int) System.currentTimeMillis(), notification);
    }
         当然上面是我修改之后的代码,其实关键的地方就在于我上面写注释的地方,解决问题一的关键在于NotificationManager的notify方法的第二个参数了。解决问题二关键就在于PendingIntent的getBroadcast方法的第二个参数。

          那我们先看看notify方法的注释:

          

/**
     * Post a notification to be shown in the status bar. If a notification with
     * the same id has already been posted by your application and has not yet been canceled, it
     * will be replaced by the updated information.
     *
     * @param id An identifier for this notification unique within your
     *        application.
     * @param notification A {@link Notification} object describing what to show the user. Must not
     *        be null.
     */
    public void notify(int id, Notification notification)
    {
        notify(null, id, notification);
    }
       可以看到注释写的很清楚,会向状态栏发送一个通知,如果我们自己应用已经发送了一个相同id的通知且没有被取消,那么之前的相同的id的notification就会被后面新发送的覆盖。这块原来也是没仔细看,既然想要唯一id,所以上面就直接放了个时间戳上去了,当然需要强转成int类型的。

      然后看第二个问题的解决方案,我们来看看getBroadcast方法的注释:

     

/**
     * Retrieve a PendingIntent that will perform a broadcast, like calling
     * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
     *
     * <p class="note">For security reasons, the {@link android.content.Intent}
     * you supply here should almost always be an <em>explicit intent</em>,
     * that is specify an explicit component to be delivered to through
     * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
     *
     * @param context The Context in which this PendingIntent should perform
     * the broadcast.
     * @param requestCode Private request code for the sender
     * @param intent The Intent to be broadcast.
     * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
     * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
     * {@link #FLAG_IMMUTABLE} or any of the flags as supported by
     * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
     * of the intent that can be supplied when the actual send happens.
     *
     * @return Returns an existing or new PendingIntent matching the given
     * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
     * supplied.
     */
    public static PendingIntent getBroadcast(Context context, int requestCode,
            Intent intent, @Flags int flags) {
        return getBroadcastAsUser(context, requestCode, intent, flags,
                new UserHandle(UserHandle.myUserId()));
    }
        哇,这个注释还是蛮多的。大致意思就是 获取生成一个PendingIntent,就会发送一个广播,就像调用了Context.sendBroadcast()方法一样子,下面说 为了安全考虑,这个方法的第三个参数intent,最好是使用显示的方式,就是使用setClass的方式声明出意向类,最好不要使用隐式意图,而我上面竟然是用的隐示意图(捂脸笑表情一个);第一个参数context就是要发送广播的上下文对象了,第二个参数requestCode,这个就是对于发送者的请求code,有点类似于我们startActivityForResult时候传递的requestCode了,所以说如果这个requestcode的值所有notification都一样,那么就会被认为是同一个意图,自然extra数据是会被覆盖的。第三个参数刚说过了,第四个参数也是蛮重要的,意思大概是说这个参数会控制当实际的发送notification发生时候可以提供哪些我们未指定的intent,应该就是intent携带的数据了;通过看注释我们发现FLAG_UPDATE_CURRENT比较适合我们的业务场景:

/**
     * Flag indicating that if the described PendingIntent already exists,
     * then keep it but replace its extra data with what is in this new
     * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
     * {@link #getService}. <p>This can be used if you are creating intents where only the
     * extras change, and don't care that any entities that received your
     * previous PendingIntent will be able to launch it with your new
     * extras even if they are not explicitly given to it.
     */
    public static final int FLAG_UPDATE_CURRENT = 1<<27;
它的大致意思是如果描述的PendingIntent已经存在,然后会保持它,但是也会用新的intent的extra替换老的extra data;这种方式可以用于如果你创建了一个只有extras发生变化的intent并且不在意之前的PendingIntent所收到的实体,所以它将会用新的extra来启动通知(当点击通知栏的通知时候)即使你不明确的指定。

         以上就是遇到的问题以及解决方法,有不对之处欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值