日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android之高仿手机QQ聊天

發布時間:2023/12/29 Android 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android之高仿手机QQ聊天 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

源代碼下載

轉載請注明出處,謝謝!

?????????最終版已上傳。優化下拉刷新、增加來消息聲音提示、主界面改成ViewPager,實現左右滑動、新增群組、最近會話顯示條數,開始上班了,不再修改了。謝謝!

??????? 國慶這幾天,閑著無聊,仿照QQ2012,做了一個基于socket的聊天工具,由于代碼比較多,今天就不在文章中貼出代碼,需要的朋友可以點擊上面下載,謝謝,后續會詳細貼出各模塊代碼,并解釋,敬請期待,O(∩_∩)O,有什么問題或者bug,歡迎給我留言。

??????? 首先說一下我的整體思路:整個聊天是通過服務器轉發的,這樣處理起來比較簡單,但是服務器壓力會特別大。建議在真正做項目的時候,服務器只處理用戶注冊、登錄以及判斷用戶是否掉線等,至于聊天、傳文件以及視頻等就在用戶之間單獨建立連接,這樣可以大大減少服務器的壓力,我這里就沒考慮這么多了。

????????第一:我們定義一個超級消息對象(記得要序列化),它包含:消息類型、具體的消息對象、發送給誰以及來自誰。服務器和客戶端就是通過發送這個超級消息對象來進行通訊的。

??????? 第二:服務器,在接受用戶連接之后,馬上把socket丟入線程池中,這樣可以支持多用戶并發訪問,然后根據用戶的socket對象,分別建立一條讀消息線程寫消息線程在這里,寫消息線程要先建立,我們需要傳遞給讀消息線程,因為我們在讀完消息之后會給用戶回復消息)。在讀消息線程里面根據消息類型處理超級消息對象,分別是:注冊、登錄、下線、轉發消息、文件、刷新好友列表等。后臺數據庫處理的話,我們通過dao模式,這樣很方便,而且會使代碼顯得簡潔、明了、有條理,總之是各種好,哈哈。最后要注意一點:因為我們是轉發消息,所以在用戶登錄成功后,我們需要把該用戶的寫消息線程根據用戶的ID存入一個Map中,以便在轉發消息的時候,可以根據用戶ID取出對應的寫消息線程,從而實現轉發消息。

???????第三:客戶端,跟服務器類似,只是沒有線程池,在用戶連接上服務器之后,也是根據連接后的socket對象,分別建立一條讀消息線程寫消息線程然后在代碼中哪里需要發消息,就通過get方法獲取寫消息線程,哪里需要讀消息,就通過get方法獲取讀消息線程

??????? 第四:關于寫消息線程處理,因為服務器或者客戶端,不可能時時需要寫消息,因此我們如果用一個死循環去處理寫線程,明顯的是不明智的,因此我做了一個簡單的處理,在寫消息的死循環中先wait(),當我們調用寫消息線程的setMessage方法后,就notify喚醒寫線程,發送完消息之后,繼續wait(),這里我貼出核心代碼:

[java]?view plaincopy
  • <span?style="font-size:14px;">?public?void?setMsg(TranObject?msg)?{??
  • ????????this.msg?=?msg;??
  • ????????synchronized?(this)?{??
  • ????????????notify();??
  • ????????}??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?run()?{??
  • ????????try?{??
  • ????????????while?(isStart)?{??
  • ????????????????if?(msg?!=?null)?{??
  • ????????????????????oos.writeObject(msg);??
  • ????????????????????oos.flush();??
  • ????????????????????if?(msg.getType()?==?TranObjectType.LOGOUT)?{//?如果是發送下線的消息,就直接跳出循環??
  • ????????????????????????break;??
  • ????????????????????}}??
  • ????????????????????synchronized?(this)?{??
  • ????????????????????????wait();//?發送完消息后,線程進入等待狀態??
  • ????????????????????}??
  • ??????????????????
  • ????????????}??
  • ????????????oos.close();//?循環結束后,關閉輸出流和socket??
  • ????????????if?(socket?!=?null)??
  • ????????????????socket.close();??
  • ????????}?catch?(InterruptedException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}?catch?(IOException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}</span>??

  • ??????? 第五:具體手機客戶端的處理,因為android有自己的特點,也有自己的優勢,所以我們要充分利用它的優勢,避開他的缺點來處理消息,我說一下我在這個小項目中處理消息的思路:我在用戶啟動程序的時候,開啟一個獲取消息的service,在該service中建立連接,然后通過一個接口去監聽讀消息線程收到的消息,在收到消息的同時,把該超級消息對象通過廣播發送出去然后自定義一個抽象的MyActivity繼承Activity,在MyActivity里面通過一個廣播接收者接收service中發送過來的消息,并通過一個抽象方法傳遞給子Activity,我們的其他activity如果要處理收消息,就可以繼承我們自定義的MyActivity,然后實現那個抽象方法,就可以了這樣很好的處理了不同的activity接收消息的缺點,而且后臺處理也很方便,我不知道騰訊QQ在這個方面是怎么處理的,這是我個人的想法而已。下面貼出MyActivity的代碼:

    [java]?view plaincopy
  • <span?style="font-size:14px;">/**?
  • ?*?自定義一個抽象的MyActivity類,每個Activity都繼承他,實現消息的接收(優化性能,減少代碼重復)?
  • ?*??
  • ?*?@author?way?
  • ?*??
  • ?*/??
  • public?abstract?class?MyActivity?extends?Activity?{??
  • ????/**?
  • ?????*?廣播接收者,接收GetMsgService發送過來的消息?
  • ?????*/??
  • ????private?BroadcastReceiver?MsgReceiver?=?new?BroadcastReceiver()?{??
  • ??
  • ????????@Override??
  • ????????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????????TranObject?msg?=?(TranObject)?intent??
  • ????????????????????.getSerializableExtra(Constants.MSGKEY);??
  • ????????????if?(msg?!=?null)?{//如果不是空,說明是消息廣播??
  • ????????????????//?System.out.println("MyActivity:"?+?msg);??
  • ????????????????getMessage(msg);//?把收到的消息傳遞給子類??
  • ????????????}?else?{//如果是空消息,說明是關閉應用的廣播??
  • ????????????????close();??
  • ????????????}??
  • ????????}??
  • ????};??
  • ??
  • ????/**?
  • ?????*?抽象方法,用于子類處理消息,?
  • ?????*??
  • ?????*?@param?msg?
  • ?????*????????????傳遞給子類的消息對象?
  • ?????*/??
  • ????public?abstract?void?getMessage(TranObject?msg);??
  • ??
  • ????/**?
  • ?????*?子類直接調用這個方法關閉應用?
  • ?????*/??
  • ????public?void?close()?{??
  • ????????Intent?i?=?new?Intent();??
  • ????????i.setAction(Constants.ACTION);??
  • ????????sendBroadcast(i);??
  • ????????finish();??
  • ????}??
  • ??
  • ????@Override??
  • ????public?void?onStart()?{//?在start方法中注冊廣播接收者??
  • ????????super.onStart();??
  • ????????IntentFilter?intentFilter?=?new?IntentFilter();??
  • ????????intentFilter.addAction(Constants.ACTION);??
  • ????????registerReceiver(MsgReceiver,?intentFilter);//?注冊接受消息廣播??
  • ??
  • ????}??
  • ??
  • ????@Override??
  • ????protected?void?onStop()?{//?在stop方法中注銷廣播接收者??
  • ????????super.onStop();??
  • ????????unregisterReceiver(MsgReceiver);//?注銷接受消息廣播??
  • ????}??
  • }??
  • </span>??
  • ?

    ?????? 好了,大概思路就是這樣的,下面根據具體的測試截圖,說說我的思路:

    1.桌面快捷方式????????????????????????????????????????????????????????????????????? ?? 2.歡迎界面

    ????????

    ?

    3.正在登陸???????????????????????????????????????????????????????????????????????????????? 4.登陸成功后的好友列表,通過ViewPager實現

    ???????

    ?

    5.好友列表是自定義的ExpandableListView,可以下拉刷新????????6.群組聊天功能暫未實現

    ??????????????????

    ?

    7.聊天主界面,???????????????????????????????????????????????????????????????????????????8.ViewPager實現左右滑動

    ??????

    ?

    9.最近會話顯示????????????????????????????????????????????????????????????????????????10.未進入聊天界面時,來消息提醒,并保存數據庫

    ???????

    ?

    11.后臺運行來消息時提醒,有聲音有振動,左圖為收到新消息,右圖為無新消息時狀態,

    ??

    ?

    12.后臺數據庫(上:user表,下:好友列表),密碼通過MD5方式加密了,用戶注冊成功后,即生成一個以用戶id命名的表,用來保存好友。

    ?

    ?

    13.服務器運行提示

    ?

    14.注冊狀態已經成功后的提示

    ?

    ?

    最后來幾張聊天截圖,好了今天就到這里,后續會繼續跟大家分享其他各個小模塊的具體實現,先休息一下,玩兩天,馬上要上班了,吼吼....

    ?

    總結

    以上是生活随笔為你收集整理的Android之高仿手机QQ聊天的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。