自定义通知

背景:最近的项目有个新需求,需要实现自定义通知样式和内容,样式如下
在这里插入图片描述
项目里已经集成极光,只不过没有做定制,采用的是极光api提供的BasicPushNotificationBuilder样式,CustomPushNotificationBuilder倒是可以实现小改动的部分定制,但是需求这样的变动不能实现,所以放弃通知,改用极光的自定义消息来处理,期间遇到一些问题,所以在此记录下。
大的原则不变,还是采用极光推送,极光的集成配置这里就不描述了。
主要的逻辑处理是在自定义的Receiver里
1.首先设置全局的NotificationManager对象,来处理接收到自定义消息本地发通知

 private NotificationManager nm;

2.onReceive方法里处理,自定义消息、通知和点击通知的跳转逻辑,代码如下

  @Override
    public void onReceive(Context context, Intent intent) {
        try {
            if (null == nm) {
                nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            }

            Bundle bundle = intent.getExtras();
            Log.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));

            if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
                String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
                Log.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);
                //send the Registration Id to your server...
            } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
                String title = bundle.getString(JPushInterface.EXTRA_TITLE);
                String message = bundle.getString(JPushInterface.EXTRA_MESSAGE);
                String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
                Log.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
                try {
                    PushJump push = new Gson().fromJson(extras, PushJump.class);
                    setCustomerMessage(context, push, title, message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
                Log.d(TAG, "[MyReceiver] 接收到推送下来的通知");
                //通知id
                int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
                //通知内容,对应 API 通知内容的 alert 字段
                String alert = bundle.getString(JPushInterface.EXTRA_ALERT);
                //通知的标题,对应 API 通知内容的 title 字段
                String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
                //附加字段。这是个 JSON 字符串,对应 API 通知内容的 extras 字段
                String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
                Log.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);
            } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
                Log.d(TAG, "[MyReceiver] 用户点击打开了通知");
                String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
                //跳转到消息列表
                Intent i = new Intent(context, MessageListActivity.class);
                i.putExtras(bundle);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                context.startActivity(i);
            } else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
                Log.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
                //在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等..

            } else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
                boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
                Log.w(TAG, "[MyReceiver]" + intent.getAction() + " connected state change to " + connected);
            } else {
                Log.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Action为JPushInterface.ACTION_MESSAGE_RECEIVED分支,对应极光自定义消息,我们的逻辑就在这个分支处理。
JPushInterface.EXTRA_TITLE
JPushInterface.EXTRA_MESSAGE
JPushInterface.EXTRA_EXTRA
分别对应对应 API 消息内容的 title 字段、 message 字段、extras 字段
极光api地址https://docs.jiguang.cn/jpush/client/Android/android_api/
接收到自定义消息之后,由于我的项目需求里自定义通知需要显示网络图片,在弹出自定义通知之前,需要首先下载处理好网络图片(异步),否则通知的图片不能加载显示,可以增加对图片大小判断处理,图片过大需要压缩否则会造成通知卡顿,由于接口已经对图片做过处理,这里我就没有对图片处理。
下载图片代码

public void setCustomerMessage(final Context context, final PushJump push, final String title, final String message) {
        new AsyncTask<String, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(String... params) {
                return getBitmap(params[0]);
            }

            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            protected void onPostExecute(final Bitmap result) {
                super.onPostExecute(result);
                showCustomerMessageNotify(context, result, title, message, push);
            }
        }.execute(push.getCustomImageUrl());
    }
private Bitmap getBitmap(String urlStr) {
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url
                    .openConnection();
            // 设置超时
            conn.setConnectTimeout(6000);
            conn.setDoInput(true);
            // 缓存
            conn.setUseCaches(true);
            conn.connect();
            int code = conn.getResponseCode();
            Bitmap bitmap = null;
            if (code == 200) {
                InputStream is = conn.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
            }
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

处理完图片之后,可以做自定义通知的处理了,先贴上代码

   @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void showCustomerMessageNotify(final Context context, Bitmap bitmap, String title, String message, final PushJump push) {
        Intent intent2 = new Intent(context, CustomerDetailActivity.class);
        intent2.putExtra("cus_id", push.getCustomId());
        if (mCountIndex != 0) {
            mCountIndex++;
        } else {
            mCountIndex = new Random().nextInt(5000) + 1;
        }
        PendingIntent pendingIntent2 = PendingIntent.getActivity(context, mCountIndex, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
        Notification.Builder builder2 = new Notification.Builder(context);
        //解决Android8.0以上版本收不到消息问题
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel mChannel = new NotificationChannel(NOTIFY_CHANNEL_ID, NOTIFY_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
            //是否显示通知指示灯
            mChannel.enableLights(true);
            //是否振动
            mChannel.enableVibration(true);
            nm.createNotificationChannel(mChannel);
            builder2.setChannelId(NOTIFY_CHANNEL_ID);
        }
        builder2.setContentIntent(pendingIntent2)
                .setSmallIcon(R.mipmap.app_logo)
                .setAutoCancel(true)
                .setContentTitle(title)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setDefaults(Notification.DEFAULT_ALL);

        Notification notification = builder2.build();

        final RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.push_notify);
        remoteViews.setTextViewText(R.id.tv_type, TextUtils.isEmpty(title) ? "客户到访提醒" : title);
        remoteViews.setTextViewText(R.id.tv_time, DateFormatUtils.getCurrentDate());
        remoteViews.setTextViewText(R.id.tv_top, message);
        remoteViews.setTextViewText(R.id.tv_middle, push.getGrade());
        remoteViews.setTextViewText(R.id.tv_bottom, push.getLastFollow());
        if (bitmap == null) {
            remoteViews.setImageViewResource(R.id.img_head, R.mipmap.default_image);
        } else {
            remoteViews.setImageViewBitmap(R.id.img_head, bitmap);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            notification.bigContentView = remoteViews;
        }

        final RemoteViews remoteViewsSmall = new RemoteViews(context.getPackageName(), R.layout.push_notify_snamll);
        remoteViewsSmall.setTextViewText(R.id.tv_title_small, TextUtils.isEmpty(title) ? "客户到访提醒" : title);
        remoteViewsSmall.setTextViewText(R.id.tv_top, message);
        remoteViewsSmall.setTextViewText(R.id.tv_middle, push.getGrade());
        remoteViewsSmall.setTextViewText(R.id.tv_bottom, push.getLastFollow());
        if (bitmap == null) {
            remoteViewsSmall.setImageViewResource(R.id.iv_small, R.mipmap.default_image);
        } else {
            remoteViewsSmall.setImageViewBitmap(R.id.iv_small, bitmap);
        }
        notification.contentView = remoteViewsSmall;

        nm.notify(mCountIndex, notification);
    }

构建自定义通知,主要处理PendingIntent和RemoteViews
PendingIntent的构造四个参数,需要注意2、4参数,参数2保证每次构建的id不同(相同的话多个通知的情况下,传值最近的通知会覆盖之前的值)
加载自定义通知布局,我采用了两个布局,最近的通知设置notification.bigContentView,其他的通知正常设置notification.contentView,
不可以全部设置bigContentView,因为bigContentView本身需要触摸滑动才会显示全部内容,全部设置的话,多条通知会显示异常。
在构建通知的时候,保证通知的id不同即可

nm.notify(mCountIndex, notification);

由于是自定义的通知,需要设配8.0以上版本,手动设置NotificationChannel,否则8.0以上版本,接收不到通知。

  //解决Android8.0以上版本收不到消息问题
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel mChannel = new NotificationChannel(NOTIFY_CHANNEL_ID, NOTIFY_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
            //是否显示通知指示灯
            mChannel.enableLights(true);
            //是否振动
            mChannel.enableVibration(true);
            nm.createNotificationChannel(mChannel);
            builder2.setChannelId(NOTIFY_CHANNEL_ID);
        }

通知的ChannelId和ChannelName设置全局即可,不要设置过长,避免系统截取。
安装app之后,在手机设置-通知管理,设置app的通知渠道,可以锁屏显示。
以上操作是对极光的自定义消息处理,实现自定义通知效果。
对于正常的极光通知,在JPushInterface.ACTION_NOTIFICATION_RECEIVED分支下处理即可。
正常通知的样式设置,在初始化极光之后操作

  public static void init(Context context) {
        JPushInterface.setDebugMode(true);
        JPushInterface.init(context);
        BasicPushNotificationBuilder builder = new BasicPushNotificationBuilder(context);
        builder.statusBarDrawable = R.mipmap.app_logo;
        builder.notificationFlags = Notification.FLAG_AUTO_CANCEL
                | Notification.FLAG_SHOW_LIGHTS;  //设置为自动消失和呼吸灯闪烁
        builder.notificationDefaults = Notification.DEFAULT_SOUND
                | Notification.DEFAULT_VIBRATE
                | Notification.DEFAULT_LIGHTS;  // 设置为铃声、震动、呼吸灯闪烁都要
        JPushInterface.setPushNotificationBuilder(0, builder);
    }

正常通知的跳转在Action
JPushInterface.ACTION_NOTIFICATION_OPENED分支下处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值