Android使用Websocket实现聊天室
最近的项目中要实现一个聊天的功能,类似于斗鱼TV的聊天室功能,与服务器端人商量后决定用WebSocket来做,但是在这之前我只知道Socket但是听都没有听过WebSocket,但是查看了相关的材料以后发现实现一个聊天室其实是很简单的!下面我们先来看看WebSocket。
Autobahn|Android 是由Autobahn开发一个开源的Java/Android网络库,实现了WebSocket协议和Web应用程序消息传输协议来创建本地移动的WebSocket/ WAMP的客服端。
WebSocket允许在网络上双向的发送实时消息,WAMP 为客服端增加了一个协议异步远程调用、推送、订阅。
WebSocket有以下几个特点
1.支持 WebSocket RFC6455, Draft Hybi-10+ and WAMP v1
2.支持Android 2.2以上
3.非常好的兼容性
4.高性能的异步设计
5.非常容易使用的api
6.与Android app非常好的结合
7.没有网络操作在UI线程
8.开源
下面是官网给的一段示例代码
private final WebSocketConnection mConnection = new WebSocketConnection(); private void start() { final String wsuri = "ws://localhost:9000"; try { mConnection.connect(wsuri, new WebSocketHandler() { @Override public void onOpen() { Log.d(TAG, "Status: Connected to " + wsuri); mConnection.sendTextMessage("Hello, world!"); } @Override public void onTextMessage(String payload) { Log.d(TAG, "Got echo: " + payload); } @Override public void onClose(int code, String reason) { Log.d(TAG, "Connection lost."); } }); } catch (WebSocketException e) { Log.d(TAG, e.toString()); } }
是不是挺简单的,在onOpen()方法中做与服务器连接的操作,onTextMessage()是收到服务器发送给客服端的消息,onClose()是与服务器断开走的方法,发送消息用sendTextMessage()。
我是在MsgService 实现与服务器的连接与发送消息的,直接上代码:
public class MsgService extends Service { private final IBinder binder = new MsgBinder(); private boolean flag = false; private WebSocketConnection mConnection; private Intent intent = new Intent("com.example.communication.RECEIVER"); public void startSocket(String sn) { final String wsuri = "ws://localhost:9000"; final JSONObject json = new JSONObject(); try { json.put("type", "command"); json.put("command", "auth"); json.put("key", Constants.API_KEY); json.put("access_token", UserManager.getInstance().getUser() .getUserAccessToken()); json.put("user_token", UserManager.getInstance().getUser() .getLYUserToken()); json.put("sn", sn); } catch (Exception e) { e.printStackTrace(); } try { mConnection.connect(wsuri, new WebSocketHandler() { @Override public void onOpen() { if (!flag) { //与服务器连接认证 mConnection.sendTextMessage(json.toString()); } else { } } @Override public void onTextMessage(String payload) { intent.putExtra("message", payload); sendBroadcast(intent);//发送广播给Fragment } @Override public void onClose(int code, String reason) { //连接失败也把效应的提示信息告诉用户 Map<String, String> map = new HashMap<>(); map.put("status", "failed"); map.put("type", "command"); map.put("command", "auth"); String msg = map.toString(); intent.putExtra("message", msg); sendBroadcast(intent); } }); } catch (WebSocketException e) { e.printStackTrace(); } } //发送消息的方法 public void sendMessage(String message) { mConnection.sendTextMessage(message); } @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { mConnection = new WebSocketConnection(); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } public class MsgBinder extends Binder { /** * 获取当前Service的实例 * * @return */ public MsgService getService() { return MsgService.this; } } @Override public void onDestroy() { super.onDestroy(); mConnection.disconnect(); } }
下面是Fragment的代码
public class ChatRoomFragment extends Fragment { private View view, rootView, headView; private MsgService msgService; private UListView chatlist;//因为ScrollVie与ListView有冲突,重写了ListView private static List<ChatMessage> mlist; private ChatMessage chatMessage; private ChatMessageAdapter chatMessageAdapter; private ScrollView scrollView; private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: msgService .startSocket(((PlayActivity) getActivity()).getSn()); break; default: break; } } }; //通过聊天室来更新在线人数 public interface UpdataOnlineUsersListener { public void updataOnlineUser(int number); } private UpdataOnlineUsersListener mCallback; private EditText messageEditText; private Button sendBtn; private Intent mIntent; private MsgReceiver msgReceiver; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d("time", "msg"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { // 返回一个MsgService对象 MsgService.MsgBinder binder = (MsgService.MsgBinder) service; if (binder != null) { Log.d("time", "msg"); } msgService = binder.getService(); if (msgService != null) { Log.d("time", "msg"); Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } } }; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_chat_room, container, false); return view; } public void bindChatService() { getActivity().bindService(mIntent, conn, Context.BIND_AUTO_CREATE); } public void destoryChatService() { getActivity().unbindService(conn); } @Override public void onAttach(Activity activity) { super.onAttach(activity); mCallback = (UpdataOnlineUsersListener) (activity); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // 动态注册广播接收器 msgReceiver = new MsgReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.communication.RECEIVER"); getActivity().registerReceiver(msgReceiver, intentFilter); mIntent = new Intent(getActivity(), MsgService.class); bindChatService(); chatlist = (UListView) view.findViewById(R.id.chatlist); messageEditText = (EditText) view.findViewById(R.id.input); scrollView = (ScrollView) view.findViewById(R.id.scroll); scrollView.setFocusable(false); mlist = new ArrayList<ChatMessage>(); chatMessageAdapter = new ChatMessageAdapter(mlist, getActivity()); chatlist.setAdapter(chatMessageAdapter); chatlist.setVerticalScrollBarEnabled(true); sendBtn = (Button) view.findViewById(R.id.send); builder = new AlertDialog.Builder(getActivity()); sendBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final View view = v; if (UserManager.getInstance().getUser().getGuest()) { ToastUtil.getInstance().showToast(getActivity(), getResources().getString(R.string.is_not_login)); } else { String message = messageEditText.getText().toString(); if (!message.equals("")) { JSONObject json = new JSONObject(); try { json.put("type", "message"); json.put("to", ""); json.put("message", message); } catch (Exception e) { } msgService.sendMessage(json.toString()); } else { Toast.makeText(getActivity(), getResources().getString(R.string.textisnull), Toast.LENGTH_SHORT).show(); } } HideKeyboard(v); messageEditText.setText(""); } }); rootView = (View) view.findViewById(R.id.rootview); rootView.setFocusable(true); rootView.setFocusableInTouchMode(true); rootView.requestFocus(); setRetainInstance(true); } //隐藏软键盘 private void HideKeyboard(View v) { InputMethodManager imm = (InputMethodManager) v.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isActive()) { imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0); } } @Override public void onResume() { super.onResume(); scrollView.smoothScrollTo(0, 0); } //接受服务端发送的消息 public class MsgReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg = intent.getStringExtra("message"); try { JSONObject json = new JSONObject(msg); if (json.getString("type").equals("command")) { String command = json.getString("command"); if (command.equals("auth")) { { chatMessage = new ChatMessage("tips", "服务器连接中...", "111", "111"); mlist.add(chatMessage); chatMessageAdapter.notifyDataSetChanged(); } if (json.getString("status").equals("success")) { chatMessage = new ChatMessage("tips", "服务器连接中成功", "111", "111"); } else { chatMessage = new ChatMessage("tips", "服务器连接中失败", "111", "111"); } mlist.add(chatMessage); chatMessageAdapter.notifyDataSetChanged(); } else if (command.equals("online_status")) { int onlineUser = json.getInt("online"); mCallback.updataOnlineUser(onlineUser); } } else if (json.getString("type").equals("message")) { chatMessage = new ChatMessage(json.getString("type"), json.getString("from"), json.getString("content"), json.getString("time")); mlist.add(chatMessage); chatMessageAdapter.notifyDataSetChanged(); } Log.d("time", mlist.toString()); } catch (JSONException e) { e.printStackTrace(); } chatlist.setSelection(chatMessageAdapter.getCount());//让ListView滑到最下面 } } @Override public void onDestroy() { // 停止服务 getActivity().unbindService(conn); // 注销广播 getActivity().unregisterReceiver(msgReceiver); super.onDestroy(); } }
这样一个简单的聊天室功能就实现了直接上图。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Android的webview支持HTML5的离线应用功能详细配置
HTML5的离线应用功能可以使得WebApp即使在网络断开的情况下仍能正常使用这是个非常有用的功能,但如何使Webivew支持HTML5离线应用功能呢,需要的朋友可以参考下2012-12-12Android自定义控件实现圆形进度CircleProgressBar
这篇文章主要为大家详细介绍了Android自定义控件实现圆形进度CircleProgressBar,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2020-05-05使用android studio导入模块的两种方法(超详细)
这篇文章主要介绍了使用android studio导入模块的两种方法,本文通过图文并茂的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下2018-09-09Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo)
本篇文章介绍了Android App支付系列(二):支付宝SDK接入详细指南(附官方支付demo) ,有兴趣的同学可以了解一下。2016-11-11Android编程连接MongoDB及增删改查等基本操作示例
这篇文章主要介绍了Android编程连接MongoDB及增删改查等基本操作,简单介绍了MongoDB功能、概念、使用方法及Android操作MongoDB数据库的基本技巧,需要的朋友可以参考下2017-07-07
最新评论