Android推送进阶课程学习笔记
今天在慕課網(wǎng)學習了Android進階課程推送的server端處理回執(zhí)的消息 。
這集課程主要介紹了,當server往client推送消息的時候,client須要發(fā)送一個回執(zhí)回來確認收到了推送消息才算一次完整的推送過程。
詳細的實現(xiàn)方法為server推送一個消息到client的時候,會生成一個相應(yīng)的uuid標識這個消息,并把這個消息以及uuid存儲到數(shù)據(jù)庫中。client收到消息后,取出當中的uuid并將這個uuid發(fā)給server端,服務(wù)端收到這個uuid。依據(jù)uuid到數(shù)據(jù)庫里刪除了相應(yīng)的消息記錄,整個推送算完畢。
這里先貼出比較核心的發(fā)送代碼
public void sendNotifcationToUser(String apiKey, String username,String title, String message, String uri) {log.debug("sendNotifcationToUser()...");Random random = new Random();//這個id就是client發(fā)送回執(zhí)相應(yīng)的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);}}//無論用戶存在不存在都須要將消息存入數(shù)據(jù)庫,直到用戶收到消息發(fā)送回饋之后再刪除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的時候都會做入庫操作。
同一時候,源碼里還有個業(yè)務(wù)邏輯,當server端檢測到client從離線到上線狀態(tài)的時候,會去數(shù)據(jù)庫查找是否有該客戶的的消息,有的話就會取出來發(fā)送,代碼例如以下
這個代碼存在的一個bug是,當檢測到有消息要給剛上線的client發(fā)送的時候。調(diào)用發(fā)送方法sendNotifcationToUser。并從數(shù)據(jù)庫刪除掉了原來的消息。這樣操作后,會發(fā)如今sendNotifcationToUser里入庫的消息被
mNotificationSevice.deleteNotification(notification);也一起刪除了(當然原來的入庫的消息也一起刪除,但這個刪除是正確的),而剛剛?cè)霂斓哪菞l消息是不應(yīng)該刪除的,必須等client發(fā)送回執(zhí)回來后再刪除。
視頻作者郭神對這個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發(fā)送回執(zhí)相應(yīng)的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);}}//無論用戶存在不存在都須要將消息存入數(shù)據(jù)庫,直到用戶收到消息發(fā)送回饋之后再刪除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上線而且數(shù)據(jù)庫有之前發(fā)送失敗的消息得推送的時候,傳入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);}}這樣改完測了之后,發(fā)現(xiàn)沒有不論什么問題,client從離線到上線后,原本存在數(shù)據(jù)庫的消息都沒有了,滿足了需求。
可是。事實上是有問題的,當client從離線到上線而且server端從數(shù)據(jù)庫檢測到有消息得推送的時候,由于傳入sendNotifcationToUser的最后一個參數(shù)是false,根本沒有做入庫操作。所以數(shù)據(jù)庫根本沒有這條發(fā)送消息的數(shù)據(jù),client收到消息發(fā)送回執(zhí)后,server沒有相應(yīng)的數(shù)據(jù)能夠刪除,導(dǎo)致看起來似乎達到了預(yù)期的效果。
針對這個問題。我做的改動例如以下,針對client從離線到在線的狀態(tài)并須要推送之前為推送成功的消息,從數(shù)據(jù)庫取出數(shù)據(jù),直接推送該消息,不刪除該消息。也不再插入新消息,等收到client回執(zhí)后再刪除。
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);}}//無論用戶存在不存在都須要將消息存入數(shù)據(jù)庫,直到用戶收到消息發(fā)送回饋之后再刪除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字段,每次發(fā)送消息,id消息都是生成一個新的。對于發(fā)送之前的消息。全然不是必需生成新的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。就是又一次發(fā)送消息的時候不再入庫消息,而是取出之前的消息來發(fā)送。等收到client回執(zhí)后再刪除。總結(jié)
以上是生活随笔為你收集整理的Android推送进阶课程学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android6.0执行时权限解析,Rx
- 下一篇: 如何开启Windows 10隐藏的锁屏时