Android推送进阶课程学习笔记

今天在慕课网学习了Android进阶课程推送的server端处理回执的消息

这集课程主要介绍了,当server往client推送消息的时候,client须要发送一个回执回来确认收到了推送消息才算一次完整的推送过程。
详细的实现方法为server推送一个消息到client的时候,会生成一个相应的uuid标识这个消息,并把这个消息以及uuid存储到数据库中。client收到消息后,取出当中的uuid并将这个uuid发给server端,服务端收到这个uuid。依据uuid到数据库里删除了相应的消息记录,整个推送算完毕。

这里先贴出比較核心的发送代码

public void sendNotifcationToUser(String apiKey, String username,
            String title, String message, String uri) {
        log.debug("sendNotifcationToUser()...");
        Random random = new Random();
        //这个id就是client发送回执相应的uuid
            String id = Integer.toHexString(random.nextInt());
        IQ notificationIQ = createNotificationIQ(id, apiKey, title, message, uri);
        ClientSession session = sessionManager.getSession(username);
        if (session != null) {
            if (session.getPresence().isAvailable()) {
                notificationIQ.setTo(session.getAddress());
                session.deliver(notificationIQ);
            }
            else{
                saveNotification(apiKey, username, title, message, uri, id);
            }
        }
        //无论用户存在不存在都须要将消息存入数据库,直到用户收到消息发送回馈之后再删除
        try {
            User user = mUserService.getUserByUsername(username);
            if(null != user){
                saveNotification(apiKey, username, title, message, uri, id);
            }
        } catch (UserNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

能够看到,每次推送消息给client的时候都会做入库操作。


同一时候,源码里还有个业务逻辑,当server端检測到client从离线到上线状态的时候,会去数据库查找是否有该客户的的消息,有的话就会取出来发送,代码例如以下

List<Notification> list = mNotificationSevice.findNotificationByUsername(session.getUsername());
                    if(null != list && list.size() > 0){
                        for(Notification notification: list){
                            String apiKey = notification.getApiKey();
                            String title = notification.getTitle();
                            String message = notification.getMessage();
                            String uri = notification.getUri();

                            mNotificationManager.sendNotifcationToUser(apiKey, session.getUsername(), title, message, uri);
                            mNotificationSevice.deleteNotification(notification);
                        }
                    }

这个代码存在的一个bug是,当检測到有消息要给刚上线的client发送的时候。调用发送方法sendNotifcationToUser。并从数据库删除掉了原来的消息。这样操作后,会发如今sendNotifcationToUser里入库的消息被
mNotificationSevice.deleteNotification(notification);也一起删除了(当然原来的入库的消息也一起删除,但这个删除是正确的),而刚刚入库的那条消息是不应该删除的,必须等client发送回执回来后再删除。

视频作者郭神对这个bug的解决方法例如以下。先直接贴出代码

public void sendNotifcationToUser(String apiKey, String username,
            String title, String message, String uri, boolean shouldSave) {
        log.debug("sendNotifcationToUser()...");
        Random random = new Random();
        //这个id就是client发送回执相应的uuid
            String id = Integer.toHexString(random.nextInt());
        IQ notificationIQ = createNotificationIQ(id, apiKey, title, message, uri);
        ClientSession session = sessionManager.getSession(username);
        if (session != null) {
            if (session.getPresence().isAvailable()) {
                notificationIQ.setTo(session.getAddress());
                session.deliver(notificationIQ);
            }
            else{
                saveNotification(apiKey, username, title, message, uri, id);
            }
        }
        //无论用户存在不存在都须要将消息存入数据库,直到用户收到消息发送回馈之后再删除
        try {
            User user = mUserService.getUserByUsername(username);
            if(null != user && shouldSave){
                saveNotification(apiKey, username, title, message, uri, id);
            }
        } catch (UserNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

以上代码添加了一个字段shouldSave来推断是否入库,同一时候在检測到client上线而且数据库有之前发送失败的消息得推送的时候,传入false

if(null != list && list.size() > 0){
                        for(Notification notification: list){
                            String apiKey = notification.getApiKey();
                            String title = notification.getTitle();
                            String message = notification.getMessage();
                            String uri = notification.getUri();

                            mNotificationManager.sendNotifcationToUser(apiKey, session.getUsername(), title, message, uri, false);
                            mNotificationSevice.deleteNotification(notification);
                        }
                    }

这样改完測了之后,发现没有不论什么问题,client从离线到上线后,原本存在数据库的消息都没有了,满足了需求。

可是。事实上是有问题的,当client从离线到上线而且server端从数据库检測到有消息得推送的时候,由于传入sendNotifcationToUser的最后一个參数是false,根本没有做入库操作。所以数据库根本没有这条发送消息的数据,client收到消息发送回执后,server没有相应的数据能够删除,导致看起来似乎达到了预期的效果。

针对这个问题。我做的改动例如以下,针对client从离线到在线的状态并须要推送之前为推送成功的消息,从数据库取出数据,直接推送该消息,不删除该消息。也不再插入新消息,等收到client回执后再删除。

public void sendNotifcationToUser(String id, String apiKey, String username,
            String title, String message, String uri, boolean shouldSave) {
        log.debug("sendNotifcationToUser()...");
        IQ notificationIQ = createNotificationIQ(id, apiKey, title, message, uri);
        ClientSession session = sessionManager.getSession(username);
        if (session != null) {
            if (session.getPresence().isAvailable()) {
                notificationIQ.setTo(session.getAddress());
                session.deliver(notificationIQ);
            }
            else if(shouldSave){
                saveNotification(apiKey, username, title, message, uri, id);
            }
        }
        //无论用户存在不存在都须要将消息存入数据库,直到用户收到消息发送回馈之后再删除
        try {
            User user = mUserService.getUserByUsername(username);
            if(null != user && shouldSave){
                saveNotification(apiKey, username, title, message, uri, id);
            }
        } catch (UserNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

这里还多了id字段,每次发送消息,id消息都是生成一个新的。对于发送之前的消息。全然不是必需生成新的id(即uuid),取出原来消息的id即可了,查找消息的地方改为例如以下

List<Notification> list = mNotificationSevice.findNotificationByUsername(session.getUsername());
                    if(null != list && list.size() > 0){
                        for(Notification notification: list){
                            String apiKey = notification.getApiKey();
                            String title = notification.getTitle();
                            String message = notification.getMessage();
                            String uri = notification.getUri();
                            String id = notification.getUuid();
                            mNotificationManager.sendNotifcationToUser(id, apiKey, session.getUsername(), title, message, uri, false);
                        }
                    }
这样就能够避免作者郭神的bug。事实上思路非常easy。就是又一次发送消息的时候不再入库消息,而是取出之前的消息来发送。等收到client回执后再删除。

转载于:https://www.cnblogs.com/zhchoutai/p/7359452.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. Android 的基本概念 Android 是一个开源的操作系统,主要用于移动设备,如智能手机、平板电脑等。它基于 Linux 内核,提供了丰富的应用程序框架和 API,支持多种开发语言,如 Java、C/C++、Kotlin 等。 Android 应用程序由多个组件组成,包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)等。这些组件可以组合在一起,形成复杂的应用程序。 2. Android 应用程序开发 Android 应用程序开发主要使用 Java 编程语言和 Android SDK。开发工具包括 Android Studio、Eclipse 等。 Android 应用程序的结构包括布局文件、资源文件、Java 代码和清单文件等。布局文件用于定义应用程序的用户界面,资源文件包括图像、声音、样式、主题等,Java 代码实现应用程序的逻辑,清单文件描述应用程序的组件和权限等信息。 3. Android 应用程序的调试和测试 Android 应用程序的调试和测试可以使用 Android Studio 提供的调试工具,包括断点调试、日志记录等。还可以使用模拟器或真实设备进行测试。 4. Android 应用程序的发布 发布 Android 应用程序需要进行签名和打包操作,签名用于验证应用程序的身份和完整性,打包将应用程序打包成 APK 文件,可以上传到应用商店进行发布。 5. Android 应用程序的优化 Android 应用程序的优化包括优化布局、资源、代码和网络等方面,以提高应用程序的性能和用户体验。其中,布局优化包括使用布局最优化算法、使用自定义视图等;资源优化包括压缩资源、使用向量图形等;代码优化包括使用异步任务、使用缓存等;网络优化包括使用数据压缩、使用本地存储等。 6. Android 开发的挑战 Android 开发面临的挑战包括设备碎片化、安全问题、性能问题等。设备碎片化指的是不同设备的屏幕尺寸、分辨率、操作系统版本等不同,需要对应用程序进行适配;安全问题指的是应用程序需要保证用户数据的安全和隐私;性能问题指的是应用程序需要保证快速响应和流畅运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值