• <kbd id="qyk40"></kbd>
  • <strike id="qyk40"></strike><samp id="qyk40"><pre id="qyk40"></pre></samp>

    一直在仿微信界面,今天終于有幸利用百度云推送仿一仿微信聊天了~~~

    首先特別感謝:weidi1989分享的Android之基于百度云推送IM ,大家可以直接下載;省了很多事哈,本例中也使用了weidi的部分代碼,凡是@author way的就是weidi1989的代碼~~

    1、效果圖

    核心功能也就上面的兩張圖了~~~我拿著手機(jī)和模擬器聊天,同時(shí)感謝群里的兄弟姐妹幫忙測(cè)試(好友列表中)。

    2、原理

    下面通過(guò)幾個(gè)問(wèn)題來(lái)說(shuō)明下實(shí)現(xiàn)的原理:

    1、如何實(shí)現(xiàn)給某個(gè)用戶(hù)發(fā)送消息呢?

    其實(shí)就是利用百度云提供的REST API,直接通過(guò)發(fā)送Http請(qǐng)求的形式給某個(gè)用戶(hù)推送一條消息;

    網(wǎng)址:http://developer.baidu.com/wiki/index.php?title=docs/cplat/push/api/list

    實(shí)例:

    push_msg
    功能
    推送消息,該接口可用于推送單個(gè)人、一群人、所有人以及固定設(shè)備的使用場(chǎng)景。
    HTTP請(qǐng)求方式
    POST
    URL
    http[s]://channel.api.duapp.com/rest/2.0/channel/channel

    ....

    2、的確可以實(shí)現(xiàn)給某個(gè)用戶(hù)或者一群用戶(hù)推送消息,那么用戶(hù)的昵稱(chēng)神馬的咋獲取的呢,我印象中百度云中沒(méi)法存這樣的數(shù)據(jù)?

    嗯,其實(shí)用了一個(gè)比較巧妙的方式;在用戶(hù)首次安裝軟件的時(shí)候,會(huì)要求用戶(hù)填寫(xiě)注冊(cè)信息,也就是昵稱(chēng)等;當(dāng)用戶(hù)填寫(xiě)完畢時(shí),點(diǎn)擊登錄的時(shí)候:

    1、發(fā)送一條比較特殊的消息,比如這個(gè)消息攜帶一個(gè)hello的字段,廣播給所有用戶(hù);

    2、其他用戶(hù)在收到消息時(shí),首先判斷hello這個(gè)字段是否有值,有值則說(shuō)明新用戶(hù)加入,把該新用戶(hù)存入本地?cái)?shù)據(jù)庫(kù),然后更新用戶(hù)列表;

    3、其他用戶(hù)給這個(gè)新用戶(hù)回一條消息,附帶一個(gè)特殊字段,比如welcome,當(dāng)新用戶(hù)收到攜帶welcome字段的消息時(shí),表明這是對(duì)新用戶(hù)hello的答復(fù),然后將已存在用戶(hù)添加到該新用戶(hù)的用戶(hù)列表。

    基本原理就這樣了,大家甚至可以利用上述的原理添加一些刪除好友的功能;比如當(dāng)用戶(hù)點(diǎn)擊刪除好友,則發(fā)送一條特殊消息給被刪除的對(duì)象,然后對(duì)方收到該消息,也將發(fā)送發(fā)刪除。

    相信大家在了解原理之后,這個(gè)例子瞬間從高大尚變成矮矬窮了,這尼瑪,so easy,誰(shuí)不會(huì)啊~~~

     

    3、核心代碼解析

    由于代碼量還是相當(dāng)大的,也不想拆成幾篇博客,所以準(zhǔn)備將核心代碼進(jìn)行講解下,其他的大家自己看源碼~

    關(guān)于這個(gè)例子的主界面,可以參考: 高仿微信5.2.1主界面架構(gòu) 包含消息通知

    關(guān)于百度云推送的入門(mén),可以參考:Android推送 百度云推送 入門(mén)篇

    好了,最主要就是收到百度云推送的Receiver

    1、onBind

    首先是用戶(hù)第一次登錄時(shí)候綁定的回調(diào)

    [java] view plaincopy在CODE上查看代碼片派生到我的代碼片

    1. @Override  

    2.     public void onBind(final Context context, int errorCode, String appid,  

    3.             String userId, String channelId, String requestId)  

    4.     {  

    5.         String responseString = "onBind errorCode=" + errorCode + " appid="  

    6.                 + appid + " userId=" + userId + " channelId=" + channelId  

    7.                 + " requestId=" + requestId;  

    8.         Log.e(TAG, responseString);  

    9.   

    10.         if (errorCode == 0)  

    11.         {  

    12.             SharePreferenceUtil util = PushApplication.getInstance()  

    13.                     .getSpUtil();  

    14.             util.setAppId(appid);  

    15.             util.setChannelId(channelId);  

    16.             util.setUserId(userId);  

    17.               

    18.         } else  

    19.         // 如果網(wǎng)絡(luò)正常,則重試  

    20.         {  

    21.             if (NetUtil.isNetConnected(context))  

    22.             {  

    23.   

    24.                 T.showLong(context, "啟動(dòng)失敗,正在重試...");  

    25.                 new Handler().postDelayed(new Runnable()  

    26.                 {  

    27.                     @Override  

    28.                     public void run()  

    29.                     {  

    30.                         PushManager.startWork(context,  

    31.                                 PushConstants.LOGIN_TYPE_API_KEY,  

    32.                                 PushApplication.API_KEY);  

    33.                     }  

    34.                 }, 2000);// 兩秒后重新開(kāi)始驗(yàn)證  

    35.             } else  

    36.             {  

    37.                 T.showLong(context, R.string.net_error_tip);  

    38.             }  

    39.         }  

    40.         // 回調(diào)函數(shù)  

    41.         for (int i = 0; i < bindListeners.size(); i++)  

    42.             bindListeners.get(i).onBind(userId, errorCode);  

    43.     }  

    初次綁定的時(shí)候,如果綁定成功則使用SharedPreferences存儲(chǔ)userId,channelId等數(shù)據(jù)

    然后回調(diào):bindListeners.get(i).onBind(userId, errorCode);給所有注冊(cè)該事件的發(fā)出通知

    下面看listener.onBind

    [java] view plaincopy在CODE上查看代碼片派生到我的代碼片

    1. /**

    2.      * 收到通知

    3.      */  

    4.     @Override  

    5.     public void onBind(String userId, int errorCode)  

    6.     {  

    7.         Log.e("TAG""Login Activity onBind ");  

    8.         if (errorCode == 0)  

    9.         {  

    10.             Log.e("TAG""Login Activity onBind success ");  

    11.             // 如果綁定賬號(hào)成功,由于第一次運(yùn)行,給同一tag的人推送一條新人消息  

    12.             User u = new User(mSpUtil.getUserId(), mSpUtil.getChannelId(),  

    13.                     mSpUtil.getNick(), mSpUtil.getHeadIcon(), 0);  

    14.             mUserDB.addUser(u);// 把自己添加到數(shù)據(jù)庫(kù)  

    15.             Message firstSendMsg = new Message(System.currentTimeMillis(), "");  

    16.             firstSendMsg.setHello("hello");  

    17.             task = new SendMsgAsyncTask(mGson.toJson(firstSendMsg), "");  

    18.             task.setOnSendScuessListener(new OnSendScuessListener()  

    19.             {  

    20.                 @Override  

    21.                 public void sendScuess()  

    22.                 {  

    23.                     if (mLoadingDialog != null && mLoadingDialog.isVisible())  

    24.                         mLoadingDialog.dismiss();  

    25.                     mHandler.removeCallbacks(mConnTimeoutCallback);  

    26.                     finish();  

    27.                     Intent intent = new Intent(LoginActivity.this,  

    28.                             MainActivity.class);  

    29.                     startActivity(intent);  

    30.                 }  

    31.             });  

    32.             task.send();  

    33.         }  

    34.     }  

    首先將自己保存到本地?cái)?shù)據(jù)庫(kù),然后發(fā)送一個(gè)Message給所有的用戶(hù),設(shè)置一個(gè)特殊字段hello;也就是上述的原理分析中的部分~

     

    2、onMessage

    收到百度云推送的Receiver中的onMessage

    [java] view plaincopy在CODE上查看代碼片派生到我的代碼片

    1. @Override  

    2.     public void onMessage(Context context, String message,  

    3.             String customContentString)  

    4.     {  

    5.         String messageString = "收到消息 message=\"" + message  

    6.                 + "\" customContentString=" + customContentString;  

    7.         Log.e(TAG, messageString);  

    8.         Message receivedMsg = PushApplication.getInstance().getGson()  

    9.                 .fromJson(message, Message.class);  

    10.         // 對(duì)接收到的消息進(jìn)行處理  

    11.         parseMessage(receivedMsg);  

    12.   

    13.     }  

    14.   

    15.     /**

    16.      * 消息:1、攜帶hello,表示新人加入,應(yīng)該自動(dòng)回復(fù)一個(gè)world 消息; 2、普通消息;

    17.      * 

    18.      * @param msg

    19.      */  

    20.     private void parseMessage(Message msg)  

    21.     {  

    22.         String userId = msg.getUserId();  

    23.         // 自己的消息  

    24.         if (userId  

    25.                 .equals(PushApplication.getInstance().getSpUtil().getUserId()))  

    26.             return;  

    27.         if (checkHasNewFriend(msg) || checkAutoResponse(msg))  

    28.             return;  

    29.         // 普通消息  

    30.         UserDB userDB = PushApplication.getInstance().getUserDB();  

    31.         User user = userDB.selectInfo(userId);  

    32.         // 漏網(wǎng)之魚(yú)  

    33.         if (user == null)  

    34.         {  

    35.             user = new User(userId, msg.getChannelId(), msg.getNickname(), 00);  

    36.             userDB.addUser(user);  

    37.             // 通知監(jiān)聽(tīng)的面板  

    38.             for (onNewFriendListener listener : friendListeners)  

    39.                 listener.onNewFriend(user);  

    40.         }  

    41.         if (msgListeners.size() > 0)  

    42.         {// 有監(jiān)聽(tīng)的時(shí)候,傳遞下去  

    43.             for (int i = 0; i < msgListeners.size(); i++)  

    44.                 msgListeners.get(i).onNewMessage(msg);  

    45.         } else  

    46.         // 當(dāng)前沒(méi)有任何監(jiān)聽(tīng),即處理后臺(tái)狀態(tài)  

    47.         {  

    48.             // 將新來(lái)的消息進(jìn)行存儲(chǔ)  

    49.             ChatMessage chatMessage = new ChatMessage(msg.getMessage(), true,  

    50.                     userId, msg.getHeadIcon(), msg.getNickname(), false,  

    51.                     TimeUtil.getTime(msg.getTimeSamp()));  

    52.             PushApplication.getInstance().getMessageDB()  

    53.                     .add(userId, chatMessage);  

    54.             showNotify(msg);  

    55.         }  

    56.     }  

    57.   

    58.     /**

    59.      * 檢測(cè)是否是自動(dòng)回復(fù)

    60.      * 

    61.      * @param msg

    62.      */  

    63.     private boolean checkAutoResponse(Message msg)  

    64.     {  

    65.         String world = msg.getWorld();  

    66.         String userId = msg.getUserId();  

    67.         if (!TextUtils.isEmpty(world))  

    68.         {  

    69.             User u = new User(userId, msg.getChannelId(), msg.getNickname(),  

    70.                     msg.getHeadIcon(), 0);  

    71.             PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友  

    72.             // 通知監(jiān)聽(tīng)的面板  

    73.             for (onNewFriendListener listener : friendListeners)  

    74.                 listener.onNewFriend(u);  

    75.   

    76.             return true;  

    77.         }  

    78.         return false;  

    79.     }  

    80.   

    81.     /**

    82.      * 檢測(cè)是否是新人加入

    83.      * 

    84.      * @param msg

    85.      */  

    86.     private boolean checkHasNewFriend(Message msg)  

    87.     {  

    88.         String userId = msg.getUserId();  

    89.         String hello = msg.getHello();  

    90.         // 新人發(fā)送的消息  

    91.         if (!TextUtils.isEmpty(hello))  

    92.         {  

    93.             Log.e("checkHasNewFriend", msg.getUserId());  

    94.             // 新人  

    95.             User u = new User(userId, msg.getChannelId(), msg.getNickname(),  

    96.                     msg.getHeadIcon(), 0);  

    97.             PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友  

    98.             T.showShort(PushApplication.getInstance(), u.getNick() + "加入");  

    99.   

    100.             // 給新人回復(fù)一個(gè)應(yīng)答  

    101.             Message message = new Message(System.currentTimeMillis(), "");  

    102.             message.setWorld("world");  

    103.             new SendMsgAsyncTask(PushApplication.getInstance().getGson()  

    104.                     .toJson(message), userId);  

    105.             // 通知監(jiān)聽(tīng)的面板  

    106.             for (onNewFriendListener listener : friendListeners)  

    107.                 listener.onNewFriend(u);  

    108.   

    109.             return true;  

    110.         }  

    111.   

    112.         return false;  

    113.     }  


    當(dāng)收到一個(gè)新的消息:

    1、首先判斷是不是自己發(fā)的,是,忽略;

    2、判斷是否攜帶hello字段,代表新人加入,攜帶,則保存到好友列表,且回復(fù)一個(gè)攜帶welcome字段的消息;

    3、判斷是否包含welcome字段,包含,存入好友列表

    4、不是1、2、3則肯定是普通消息,將消息保存到本地?cái)?shù)據(jù)庫(kù),然后為所有設(shè)置消息監(jiān)聽(tīng)的發(fā)送回調(diào)即可~

     

    MainTabFriends.java用戶(hù)列表中收到新消息的回調(diào):

    [java] view plaincopy在CODE上查看代碼片派生到我的代碼片

    1. /**

    2.      * 收到新消息時(shí)

    3.      */  

    4.     @Override  

    5.     public void onNewMessage(Message message)  

    6.     {  

    7.         // 如果是自己發(fā)送的,則直接返回  

    8.         if (message.getUserId() == mSpUtils.getUserId())  

    9.             return;  

    10.         // 如果該用戶(hù)已經(jīng)有未讀消息,更新未讀消息的個(gè)數(shù),并通知更新未讀消息接口,最后notifyDataSetChanged  

    11.         String userId = message.getUserId();  

    12.         if (mUserMessages.containsKey(userId))  

    13.         {  

    14.             mUserMessages.put(userId, mUserMessages.get(userId) + 1);  

    15.         } else  

    16.         {  

    17.             mUserMessages.put(userId, 1);  

    18.         }  

    19.         mUnReadedMsgs++;  

    20.         notifyUnReadedMsg();  

    21.         // 將新來(lái)的消息進(jìn)行存儲(chǔ)  

    22.         ChatMessage chatMessage = new ChatMessage(message.getMessage(), true,  

    23.                 userId, message.getHeadIcon(), message.getNickname(), false,  

    24.                 TimeUtil.getTime(message.getTimeSamp()));  

    25.         mApplication.getMessageDB().add(userId, chatMessage);  

    26.         // 通知listview數(shù)據(jù)改變  

    27.         mAdapter.notifyDataSetChanged();  

    28.     }  


    1、如果是自己發(fā)的不做任何處理

    2、如果當(dāng)前消息發(fā)送用戶(hù)已有未讀消息,則更新該用戶(hù)未讀消息個(gè)數(shù)(用戶(hù)Item上顯示未讀消息通知數(shù)),更新所有未讀消息總和(朋友Tab上顯示未讀消息總和),然后存儲(chǔ)該消息

    3、刷新界面

     

    ChattingActivity.java聊天界面的新消息回調(diào)

    [java] view plaincopy在CODE上查看代碼片派生到我的代碼片

    1. @Override  

    2.     public void onNewMessage(Message message)  

    3.     {  

    4.   

    5.         // 獲得回復(fù)的消息  

    6.         if (mFromUser.getUserId().equals(message.getUserId()))  

    7.         {  

    8.             ChatMessage chatMessage = new ChatMessage();  

    9.             chatMessage.setComing(true);  

    10.             chatMessage.setDate(new Date(message.getTimeSamp()));  

    11.             chatMessage.setMessage(message.getMessage());  

    12.             chatMessage.setUserId(message.getUserId());  

    13.             chatMessage.setNickname(message.getNickname());  

    14.             chatMessage.setReaded(true);  

    15.             mDatas.add(chatMessage);  

    16.             mAdapter.notifyDataSetChanged();  

    17.             mChatMessagesListView.setSelection(mDatas.size() - 1);  

    18.             // 存入數(shù)據(jù)庫(kù),當(dāng)前聊天記錄  

    19.             mApplication.getMessageDB().add(mFromUser.getUserId(), chatMessage);  

    20.         }  

    21.     }  


    首先判斷是否是正在聊天的用戶(hù)發(fā)的消息,如果是,直接存入數(shù)據(jù)庫(kù),刷新聊天界面;

     

     

    穩(wěn)定

    產(chǎn)品高可用性高并發(fā)

    貼心

    項(xiàng)目群及時(shí)溝通

    專(zhuān)業(yè)

    產(chǎn)品經(jīng)理1v1支持

    快速

    MVP模式小步快跑

    承諾

    我們選擇聲譽(yù)

    堅(jiān)持

    10年專(zhuān)注高端品質(zhì)開(kāi)發(fā)
    • 返回頂部
    国产A√精品区二区三区四区| 在线观看亚洲精品专区| 精品国产污污免费网站| 亚洲国产精品无码久久青草| 四虎精品久久久久影院| 99久久综合精品五月天| 伊人久久精品一区二区三区| 精品人妻系列无码天堂| 人妻少妇乱子伦精品| 久久精品视频99精品视频150| 亚洲精品制服丝袜四区| 国产午夜精品一本在线观看 | 日韩在线视频不卡| 日韩久久久久中文字幕人妻| 国产精品深夜福利免费观看| 国产99视频精品专区| 1313午夜精品理论片| 久久99精品久久久久久清纯| 亚洲精品无播放器在线播放| 日韩视频在线精品视频免费观看 | 日韩好片一区二区在线看| 国产精品午夜小视频观看| 日韩精品一区在线| 狠狠精品干练久久久无码中文字幕| 3D动漫精品一区二区三区| 精品无码一区二区三区电影| 亚洲国产精品张柏芝在线观看| 久久久久99精品成人片试看 | 国产青草亚洲香蕉精品久久| 自拍偷自拍亚洲精品播放| 苍井空亚洲精品AA片在线播放 | 国产日韩精品SUV| 在线精品动漫一区二区无广告| 久久乐国产精品亚洲综合| 99久久精品国产免看国产一区| 自拍偷自拍亚洲精品第1页| 国产亚洲精品久久久久秋霞| 视频一区精品自拍| 精品精品国产自在久久高清| 国产成人精品视频一区二区不卡 | 国产精品免费看久久久|