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發送回執相應的uuidString 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 blocke.printStackTrace();}}能夠看到,每次推送消息給client的時候都會做入庫操作。
同一時候,源碼里還有個業務邏輯,當server端檢測到client從離線到上線狀態的時候,會去數據庫查找是否有該客戶的的消息,有的話就會取出來發送,代碼例如以下
這個代碼存在的一個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發送回執相應的uuidString 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 blocke.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 blocke.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回執后再刪除。總結
以上是生活随笔為你收集整理的Android推送进阶课程学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android6.0执行时权限解析,Rx
- 下一篇: 如何开启Windows 10隐藏的锁屏时