这是<是时候来了解android7>系列的第三篇文章了, 前面两篇分别介绍了多窗口模式和shortcut功能, 今天我们来点简单的, 说一说通知直接回复功能. 可能很多朋友还没有机会接触到android7的新特性, 所以在开始之前,先来介绍一下什么是通知直接回复, 拿短信应用来说吧, 在之前我们接收到一条新短信是会有一个通知提醒的, 不过假如我们想要回复该短信就要点击短信应用或者点击通知进入到短信内容里才可以, 甚是麻烦. 从android7开始, 我们不用这么麻烦了, 可以直接在通知里进行回复了!好像iOS和一些国产的ROM早就有了这项功能, 不过在原生Android里这是第一次, 这个特性既方便了用户, 同时也方便了我们开发者. 来张图感受一下.
这就是我们今天要完成的一个小demo, 先来说一下这个demo的流程, 首先, 我们点击”发通知”会模拟发出一个短信通知, 然后当我们编辑完回复内容点击发送的时候, 会启动一个service来模拟发送短信发送过程, 这个模拟过程首先会有一个延迟, 延迟后继续发送一个”发送成功”的通知, 最后将通知取消掉.
流程很简单, 整个都是模拟的过程, 最主要的是要学习一个直接回复这项新功能.
那重点来了? 如何发送一个带有直接回复功能的通知呢? 下面再来整理一下发送这样的一个通知的流程:
第一步, 我们需要创建一个RemoteInput 第二步, 创建一个PendingIntent, 这个PendingIntent指当我们点击”发送”的时候调用什么 第三步, 创建一个直接回复的Action 第四步, 创建notification 第五步, 发送通知
一共5个步骤我们就可以创建一个带有”直接回复”功能的通知了, 而且这5步里2,4,5应该是我们熟悉的代码, 下面我们就来一步步的完成代码.
首先, 创建RemoteInput
RemoteInput remoteInput = new RemoteInput.Builder(RESULT_KEY) .setLabel("回复这条消息") .build();
很简单的一个builder, 首先Builder的构造我们需要一个String类型的key, 这个key是干嘛用的? 其实就是我们方便在处理回复的时候拿内容的. 其次一个setLabel方法, 可以对照着上面的图来看看这是哪一部分的内容, 说白了, 这其实就是一个EditText的Hint值.
接下来继续第二步, 创建一个PendingIntent, 这个PendingIntent在这里的作用是启动一个service,所以代码是这样的:
Intent intent = new Intent(this, SendMsgService.class); PendingIntent pi = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
都是大家熟悉的代码, 我们接着来看第三步, 创建一个直接回复的Action
NotificationCompat.Action act = new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, "回复", pi) .addRemoteInput(remoteInput).build();
又是一个Builder, 这个Builder的构造中有三个参数, 第一个参数是一个logo, 搞过通知的朋友肯定对通知的logo都很熟悉了, 第二个参数是这个Action的标签, 对应上面demo中我们要点击的那个按钮, 第三个参数是当我们点击”回复”的时候要干嘛. 接下来一个addRemoteInput方法将上面我们创建的RemoteInput传递进来.
第四步, 创建一个notification, 这个过程中大家都知道也是一个builder, 不过这个builder中肯定有我们不熟悉的方法, 要们上面的Action怎么设置呢?
NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("请问是否需要信用卡?") .setContentText("您好,我是XX银行的XX经理, 请问你需要办理信用卡吗?") .setColor(Color.CYAN) .addAction(act) .setCategory(Notification.CATEGORY_MESSAGE);
从上往下一个个的来, 略…略…略…, setColor方法的作用是设置一个accent颜色, 对应上面的demo就是那个”回复”和点击”回复”后输入框的背景颜色. addAction方法就是将我们上面创建的Action设置进来, setCategory是指定通知的类型, 这里我们指定为消息类型.
最后一步, 发送通知
NotificationManager nm = getSystemService(NotificationManager.class); nm.notify(NOTIFICATION_ID, builder.build());
没撒好说的, 就这样简单的几步, 一个具有”直接回复”功能的通知就发出来了, 不过还没完, 虽然通知出来了, 但是用户回复的内容我们还没处理. 这些逻辑的处理我们放到上面提到的那个service里执行.
那这个处理流程是怎样的呢? 还是先来罗列下流程.
拿到用户输入的内容 模拟发送的延迟 模拟发送成功, 取消通知
再次一步步的跟代码, 首先我们要拿到用户输入的内容, 我们可以通过RemoteInput的一个静态方法getResultsFromIntent直接拿到一个Bundle, 然后我们就可以根据上面构建RemoteInput的时候使用的key来拿到内容了.
Bundle replyBundle = RemoteInput.getResultsFromIntent(intent); if (replyBundle != null) { // 根据key拿到回复的内容 String reply = replyBundle.getString(MainActivity.RESULT_KEY); reply(reply); }
拿到内容后, 我们就来模拟回复了, 这个操作是在reply方法中完成的.
private void reply(final String reply) { mHandler.postDelayed(new Runnable() { @Override public void run() { Log.d("reply", "reply: " + reply); onReply(); } }, 1000); } }
这里我们延迟1000ms后表示回复成功, 然后调用onReply方法.
private void onReply() { final NotificationManager nm = getSystemService(NotificationManager.class); mHandler.post(new Runnable() { @Override public void run() { // 更新通知为“回复成功” Notification notification = new NotificationCompat.Builder(SendMsgService.this) .setSmallIcon(R.mipmap.ic_launcher) .setContentText("回复成功") .build(); nm.notify(MainActivity.NOTIFICATION_ID, notification); } }); // 最后将通知取消 mHandler.postDelayed(new Runnable() { @Override public void run() { nm.cancel(MainActivity.NOTIFICATION_ID); } }, 2000); }
在onReply里我们就来干剩下的事了, 包括发送一个”发送成功”的消息,然后延迟取消通知.
代码很简单, 主要的是创建直接回复的通知和如何拿到用户输入的内容, 如果大家的APP中有这样的需求, 可以考虑在适配Android7的时候加入直接回复的功能.
最后来一个题外话, 从Android5开始, 其实Android还提供了一个悬浮式通知的功能, 这个悬浮式通知其实也很简单, 只需要在构建Notification的时候使用setFullScreenIntent(PendingIntent pi, boolean highPriority)即可实现, 现在Android7最新的短信应用就是结合了悬浮式通知和直接回复的功能, 不过我自己在实现的时候还是遇到了一些问题, 例如: 如何控制悬浮式通知的消失, 如何控制悬浮式通知消失后发出一个普通通知, 这两个问题我的做法是发出一个悬浮式通知后, 使用Handler延迟发送一个普通通知, 但这样还是有一个问题, 在悬浮式通知进行直接回复时, 通知可能就已经被取消了, 这里我还没有找到google短信源码看它是怎么处理的, 如果大家有知道原生消息是怎么处理的或者从哪可以找到google原生短信应用的源码可以在下面给我留言, 谢谢~
最近给出我的demo源码: https://github.com/qibin0506/N_notification_quick_reply