編輯:關於Android編程
下面通過幾個問題來說明下實現的原理:
其實就是利用百度雲提供的REST API,直接通過發送Http請求的形式給某個用戶推送一條消息;
實例:
push_msg
功能
推送消息,該接口可用於推送單個人、一群人、所有人以及固定設備的使用場景。
HTTP請求方式
POST
URL
http[s]://channel.api.duapp.com/rest/2.0/channel/channel
….
嗯,其實用了一個比較巧妙的方式;在用戶首次安裝軟件的時候,會要求用戶填寫注冊信息,也就是昵稱等;當用戶填寫完畢時,點擊登錄的時候:
1、發送一條比較特殊的消息,比如這個消息攜帶一個hello的字段,廣播給所有用戶;
2、其他用戶在收到消息時,首先判斷hello這個字段是否有值,有值則說明新用戶加入,把該新用戶存入本地數據庫,然後更新用戶列表;
3、其他用戶給這個新用戶回一條消息,附帶一個特殊字段,比如welcome,當新用戶收到攜帶welcome字段的消息時,表明這是對新用戶hello的答復,然後將已存在用戶添加到該新用戶的用戶列表。
基本原理就這樣了,大家甚至可以利用上述的原理添加一些刪除好友的功能;比如當用戶點擊刪除好友,則發送一條特殊消息給被刪除的對象,然後對方收到該消息,也將發送發刪除。
相信大家在了解原理之後,這個例子瞬間從高大尚變成矮矬窮了,這尼瑪,so easy,誰不會啊~~~
由於代碼量還是相當大的,也不想拆成幾篇博客,所以准備將核心代碼進行講解下,其他的大家自己看源碼~
關於這個例子的主界面,可以參考: 高仿微信5.2.1主界面架構 包含消息通知
關於百度雲推送的入門,可以參考:Android推送 百度雲推送 入門篇
好了,最主要就是收到百度雲推送的Receiver
首先是用戶第一次登錄時候綁定的回調
[java] view plain copy @Override public void onBind(final Context context, int errorCode, String appid, String userId, String channelId, String requestId) { String responseString = "onBind errorCode=" + errorCode + " appid=" + appid + " userId=" + userId + " channelId=" + channelId + " requestId=" + requestId; Log.e(TAG, responseString); if (errorCode == 0) { SharePreferenceUtil util = PushApplication.getInstance() .getSpUtil(); util.setAppId(appid); util.setChannelId(channelId); util.setUserId(userId); } else // 如果網絡正常,則重試 { if (NetUtil.isNetConnected(context)) { T.showLong(context, "啟動失敗,正在重試..."); new Handler().postDelayed(new Runnable() { @Override public void run() { PushManager.startWork(context, PushConstants.LOGIN_TYPE_API_KEY, PushApplication.API_KEY); } }, 2000);// 兩秒後重新開始驗證 } else { T.showLong(context, R.string.net_error_tip); } } // 回調函數 for (int i = 0; i < bindListeners.size(); i++) bindListeners.get(i).onBind(userId, errorCode); }
初次綁定的時候,如果綁定成功則使用SharedPreferences存儲userId,channelId等數據
然後回調:bindListeners.get(i).onBind(userId, errorCode);給所有注冊該事件的發出通知
下面看listener.onBind
[java] view plain copy /** * 收到通知 */ @Override public void onBind(String userId, int errorCode) { Log.e("TAG", "Login Activity onBind "); if (errorCode == 0) { Log.e("TAG", "Login Activity onBind success "); // 如果綁定賬號成功,由於第一次運行,給同一tag的人推送一條新人消息 User u = new User(mSpUtil.getUserId(), mSpUtil.getChannelId(), mSpUtil.getNick(), mSpUtil.getHeadIcon(), 0); mUserDB.addUser(u);// 把自己添加到數據庫 Message firstSendMsg = new Message(System.currentTimeMillis(), ""); firstSendMsg.setHello("hello"); task = new SendMsgAsyncTask(mGson.toJson(firstSendMsg), ""); task.setOnSendScuessListener(new OnSendScuessListener() { @Override public void sendScuess() { if (mLoadingDialog != null && mLoadingDialog.isVisible()) mLoadingDialog.dismiss(); mHandler.removeCallbacks(mConnTimeoutCallback); finish(); Intent intent = new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); } }); task.send(); } }
首先將自己保存到本地數據庫,然後發送一個Message給所有的用戶,設置一個特殊字段hello;也就是上述的原理分析中的部分~
收到百度雲推送的Receiver中的onMessage
[java] view plain copy @Override public void onMessage(Context context, String message, String customContentString) { String messageString = "收到消息 message=\"" + message + "\" customContentString=" + customContentString; Log.e(TAG, messageString); Message receivedMsg = PushApplication.getInstance().getGson() .fromJson(message, Message.class); // 對接收到的消息進行處理 parseMessage(receivedMsg); } /** * 消息:1、攜帶hello,表示新人加入,應該自動回復一個world 消息; 2、普通消息; * * @param msg */ private void parseMessage(Message msg) { String userId = msg.getUserId(); // 自己的消息 if (userId .equals(PushApplication.getInstance().getSpUtil().getUserId())) return; if (checkHasNewFriend(msg) || checkAutoResponse(msg)) return; // 普通消息 UserDB userDB = PushApplication.getInstance().getUserDB(); User user = userDB.selectInfo(userId); // 漏網之魚 if (user == null) { user = new User(userId, msg.getChannelId(), msg.getNickname(), 0, 0); userDB.addUser(user); // 通知監聽的面板 for (onNewFriendListener listener : friendListeners) listener.onNewFriend(user); } if (msgListeners.size() > 0) {// 有監聽的時候,傳遞下去 for (int i = 0; i < msgListeners.size(); i++) msgListeners.get(i).onNewMessage(msg); } else // 當前沒有任何監聽,即處理後台狀態 { // 將新來的消息進行存儲 ChatMessage chatMessage = new ChatMessage(msg.getMessage(), true, userId, msg.getHeadIcon(), msg.getNickname(), false, TimeUtil.getTime(msg.getTimeSamp())); PushApplication.getInstance().getMessageDB() .add(userId, chatMessage); showNotify(msg); } } /** * 檢測是否是自動回復 * * @param msg */ private boolean checkAutoResponse(Message msg) { String world = msg.getWorld(); String userId = msg.getUserId(); if (!TextUtils.isEmpty(world)) { User u = new User(userId, msg.getChannelId(), msg.getNickname(), msg.getHeadIcon(), 0); PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友 // 通知監聽的面板 for (onNewFriendListener listener : friendListeners) listener.onNewFriend(u); return true; } return false; } /** * 檢測是否是新人加入 * * @param msg */ private boolean checkHasNewFriend(Message msg) { String userId = msg.getUserId(); String hello = msg.getHello(); // 新人發送的消息 if (!TextUtils.isEmpty(hello)) { Log.e("checkHasNewFriend", msg.getUserId()); // 新人 User u = new User(userId, msg.getChannelId(), msg.getNickname(), msg.getHeadIcon(), 0); PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友 T.showShort(PushApplication.getInstance(), u.getNick() + "加入"); // 給新人回復一個應答 Message message = new Message(System.currentTimeMillis(), ""); message.setWorld("world"); new SendMsgAsyncTask(PushApplication.getInstance().getGson() .toJson(message), userId); // 通知監聽的面板 for (onNewFriendListener listener : friendListeners) listener.onNewFriend(u); return true; } return false; }
當收到一個新的消息:
1、首先判斷是不是自己發的,是,忽略;
2、判斷是否攜帶hello字段,代表新人加入,攜帶,則保存到好友列表,且回復一個攜帶welcome字段的消息;
3、判斷是否包含welcome字段,包含,存入好友列表
4、不是1、2、3則肯定是普通消息,將消息保存到本地數據庫,然後為所有設置消息監聽的發送回調即可~
MainTabFriends.java用戶列表中收到新消息的回調:
[java] view plain copy /** * 收到新消息時 */ @Override public void onNewMessage(Message message) { // 如果是自己發送的,則直接返回 if (message.getUserId() == mSpUtils.getUserId()) return; // 如果該用戶已經有未讀消息,更新未讀消息的個數,並通知更新未讀消息接口,最後notifyDataSetChanged String userId = message.getUserId(); if (mUserMessages.containsKey(userId)) { mUserMessages.put(userId, mUserMessages.get(userId) + 1); } else { mUserMessages.put(userId, 1); } mUnReadedMsgs++; notifyUnReadedMsg(); // 將新來的消息進行存儲 ChatMessage chatMessage = new ChatMessage(message.getMessage(), true, userId, message.getHeadIcon(), message.getNickname(), false, TimeUtil.getTime(message.getTimeSamp())); mApplication.getMessageDB().add(userId, chatMessage); // 通知listview數據改變 mAdapter.notifyDataSetChanged(); }
1、如果是自己發的不做任何處理
2、如果當前消息發送用戶已有未讀消息,則更新該用戶未讀消息個數(用戶Item上顯示未讀消息通知數),更新所有未讀消息總和(朋友Tab上顯示未讀消息總和),然後存儲該消息
3、刷新界面
ChattingActivity.java聊天界面的新消息回調
[java] view plain copy @Override public void onNewMessage(Message message) { // 獲得回復的消息 if (mFromUser.getUserId().equals(message.getUserId())) { ChatMessage chatMessage = new ChatMessage(); chatMessage.setComing(true); chatMessage.setDate(new Date(message.getTimeSamp())); chatMessage.setMessage(message.getMessage()); chatMessage.setUserId(message.getUserId()); chatMessage.setNickname(message.getNickname()); chatMessage.setReaded(true); mDatas.add(chatMessage); mAdapter.notifyDataSetChanged(); mChatMessagesListView.setSelection(mDatas.size() - 1); // 存入數據庫,當前聊天記錄 mApplication.getMessageDB().add(mFromUser.getUserId(), chatMessage); } }
首先判斷是否是正在聊天的用戶發的消息,如果是,直接存入數據庫,刷新聊天界面;
有時候使用陌陌會不會遇到密碼忘記的時候,特別是設置了復雜的密碼,更加容易忘記。忘記密碼無法登錄?別著急,小陌為您提供綁定手機情況下重置密碼的方法,請結合你的
目前很多app都會有短視頻內容,這裡就來講一下android中播放視頻的幾種方式。Android播放視頻有三種方式:1,調用系統已有的播放軟件播放視頻。2,使用andro
Android 調試工具,這裡做一個總結整理。DDMS -- Dalvik debug monitor service &n
畫類圖是一件挺麻煩的事情。如果有工具能自動生成類圖,那有多好!簡單搜索了一下,還真有。AS (2.1)下面搞一個插件code iris就可以自動生成。1 插件安裝安裝很簡