Android中使用webSocket实现文字及单张图片发送聊天功能
2017-06-21 17:41
961 查看
WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:
1. WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
2. WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。
下面主要使用“JavaWebSocket”开源项目,实现Android端与服务器端消息互通。
参考下文献:http://blog.csdn.net/tangxl2008008/article/details/52421413
http://blog.csdn.net/li352558693/article/details/42639683
http://www.cnblogs.com/lliuzl/articles/4550493.html
http://www.open-open.com/lib/view/open1476778263175.html
先看下我在项目中使用的WebSocket 通信,再介绍:
我们分析下这里的主要方法。
1.首先要添加WebSocket 的依赖,不然谁让你用啊。
2.看initData();这里初始化WebSocket :initWebSocketClient();
方法initWebSocketClient();初始化WebSocket
这里参考下文献:http://blog.csdn.net/tangxl2008008/article/details/52421413
这里有四个方法,要格外注意:
onOpen():方法是链接成功是调用。
onMessage();方法是从服务端消息(聊天时对方发过来的消息),这里显示的内容对方发过来的内容。
onClose();连接断开,remote判定是客户端断开还是服务端断开
onError();链接错误。
但是不要忘记加上:webSocketClient.connect(); 才能链接到WebSocket.
接下来看是如何发送消息的:
还有一个方法:
这是添加recycleview.smoothScrollToPosition(datas.size() - 1); 的效果;
大家看到当每收到一条消息后都会显示出来。
这是没有添加这句的效果:
大家看下就能发现问题。列表刷新后我们并没有立即看到,还有向上滑动才显示内容。
我们再看下图片的发送,这里推按只能发送一张每次,首先是上传图片,然后是为Bean赋值,刷新Adapter,这里离我急不介绍了。
不过有一点还要注意,
当我们销毁页面时:WebSocket断开连接。
1. WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
2. WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。
下面主要使用“JavaWebSocket”开源项目,实现Android端与服务器端消息互通。
参考下文献:http://blog.csdn.net/tangxl2008008/article/details/52421413
http://blog.csdn.net/li352558693/article/details/42639683
http://www.cnblogs.com/lliuzl/articles/4550493.html
http://www.open-open.com/lib/view/open1476778263175.html
先看下我在项目中使用的WebSocket 通信,再介绍:
* 聊天页面 */ public class ChatActivity extends BaseActivity { private ImageView iv_back; private TextView tv_title; private RecyclerView recycleview; private ImageView iv_add; private EditText et_text; private ImageView iv_send; private List<ChatHistoryBean.TalkDataListBean> datas; private ChatListAdapter chatListAdapter; private String content = ""; private ChatHistoryBean chatBean; private WebSocketClient webSocketClient; private ChatHistoryBean.TalkDataListBean myTalkBean; private ChatHistoryBean.TalkDataListBean myTalkBean_img;//上传图片的bean private Date date_time; private SimpleDateFormat sdf; private String link_user_id; private String link_user_name; private String link_user_image; private Boolean isMailChat; private RelativeLayout rl_titlebar; @Override public int getLayoutResId() { datas = new ArrayList<>(); isMailChat = getIntent().getBooleanExtra("isMailChat", false); return R.layout.activity_chat; } @Override protected void initView() { iv_back = (ImageView) findViewById(R.id.iv_back); iv_back.setVisibility(View.VISIBLE); rl_titlebar = (RelativeLayout) findViewById(R.id.rl_titlebar); tv_title = (TextView) findViewById(R.id.tv_title); iv_add = (ImageView) findViewById(R.id.iv_add); et_text = (EditText) findViewById(R.id.et_text); iv_send = (ImageView) findViewById(R.id.iv_send); recycleview = (RecyclerView) findViewById(R.id.recycleview); recycleview.setLayoutManager(new LinearLayoutManager(activity, LinearLayout.VERTICAL, false)); date_time = new Date(); sdf = new SimpleDateFormat("HH:mm:ss"); } @Override protected void initListener() { iv_back.setOnClickListener(this); iv_add.setOnClickListener(this); iv_send.setOnClickListener(this); } @Override protected void initData() { // tv_title.setText("连接中..."); if (isMailChat) { rl_titlebar.setBackgroundColor(getResources().getColor(R.color.titlebar_bg_blue)); } else { rl_titlebar.setBackgroundColor(getResources().getColor(R.color.titlebar_bg)); } chatListAdapter = new ChatListAdapter(activity, datas);//聊天列表 initWebSocketClient();//初始化webSocket chatBean = (ChatHistoryBean) getIntent().getSerializableExtra("bean"); if (chatBean == null) { //如果为null,表示不是从聊天历史记录中跳转过来的,而是从其他页面点击"联系我们"跳转进来的 link_user_id = getIntent().getStringExtra("link_id"); link_user_name = getIntent().getStringExtra("link_user_name"); link_user_image = getIntent().getStringExtra("link_user_image"); //获取单个人的聊天历史记录 onLoadToGetSomeBodyChatHistory(link_user_id); } else { link_user_id = chatBean.link_user_id; link_user_name = chatBean.link_user_name; link_user_image = chatBean.link_user_image; datas = chatBean.talkDataList; chatListAdapter = new ChatListAdapter(activity, datas); recycleview.setAdapter(chatListAdapter); if (datas.size() != 0) { recycleview.scrollToPosition(datas.size() - 1); } } } @Override public void onClick(View view) { super.onClick(view); switch (view.getId()) { case R.id.iv_back: finish(); break; case R.id.iv_add: //添加图片 Intent intent = new Intent(this, SelectPicActivity.class); startActivityForResult(intent, 101); break; case R.id.iv_send: //发送文字 sendMessage(); break; } } /** * 初始化websocket */ private void initWebSocketClient() { URI uri = null; try { if (isMailChat) {//员工聊天websocket的连接地址 uri = new URI(NetUtils.WS_CHAT_MAIL + SpUtils.getUserId(activity)); } else {//业务聊天websocket的连接地址 uri = new URI(NetUtils.WS_CHAT_BUSINESS + SpUtils.getUserId(activity)); } } catch (Exception e) { e.printStackTrace(); } //连接中使用的new Draft_17()就是使用的协议version 17(RFC 6455),Tomcat 7.0使用的协议版本为RFC 6455。 Draft_17 draft = new Draft_17(); webSocketClient = new WebSocketClient(uri, draft) { @Override//连接成功 public void onOpen(ServerHandshake handshakedata) { Log.d(TAG, "run() returned: " + "连接到服务器"); String title = getIntent().getStringExtra("title"); changeTitle(title); } @Override//从服务端消息(聊天时对方发过来的消息) public void onMessage(final String message) { Log.d(TAG, "run() returned: " + message); // 8735$$$$$$$$nature$$$$$$$$a0/51/97/a051979545fa49f18444fc7b2d8f6477.png$$$$$$$$8678$$$$$$$$anan$$$$$$$$db/cd/97/dbcd979f580049ae8cb6f0cbf5969f70.png$$$$$$$$0$$$$$$$$Zzzzz$$$$$$$$empty // 字符串$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$字符串 用$$$$$$$$分割 // /****自己的id**自己的昵称**自己的头像***对方id***对放昵称**对方头像****消息类型(自己还是对方)****消息字符串****图片****/ runOnUiThread(new Runnable() { @Override public void run() { try { String messages[] = message.split("\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024");//$$$$$$$$分割 myTalkBean = new ChatHistoryBean.TalkDataListBean(); myTalkBean.user_id = messages[0]; myTalkBean.user_name = messages[1]; myTalkBean.user_image = messages[2]; myTalkBean.link_user_id = messages[3]; myTalkBean.link_user_name = messages[4]; myTalkBean.link_user_image = messages[5]; myTalkBean.type = "1"; myTalkBean.text = messages[7]; myTalkBean.image = messages[8]; myTalkBean.time = sdf.format(date_time); datas.add(myTalkBean); chatListAdapter.notifyDataSetChanged(); 4000 recycleview.smoothScrollToPosition(datas.size() - 1); } catch (Exception e) { e.printStackTrace(); } } }); } @Override//连接断开,remote判定是客户端断开还是服务端断开 public void onClose(int code, String reason, boolean remote) { changeTitle("未连接"); Log.d(TAG, "onClose() returned: " + reason); } @Override public void onError(Exception ex) { Log.d(TAG, "onError() returned: " + ex); changeTitle("连接异常"); } }; webSocketClient.connect(); } /** * 发送文本消息 */ private void sendMessage() { // 字符串$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$字符串 用$$$$$$$$分割 // /****自己的id**自己的昵称**自己的头像***对方id***对放昵称**对方头像****消息类型(自己还是对方)****消息字符串****图片****/ String img; content = et_text.getEditableText().toString(); if (StringUtils.isEmpty(content)) { content = "empty"; return; } else { img = "empty"; } runOnUiThread(new Runnable() { @Override public void run() {//webSocketClient发送的文字消息,不是图片 String con = SpUtils.getUserId(activity) + "$$$$$$$$" //自己的id + SpUtils.getUserName(activity) + "$$$$$$$$" //自己的昵称 + SpUtils.getHeadimg(activity).split("files/")[1] + "$$$$$$$$" //自己的头像 + link_user_id + "$$$$$$$$" //对方id + link_user_name + "$$$$$$$$" //对放昵称 + link_user_image + "$$$$$$$$" //对方头像 + "0" + "$$$$$$$$" //消息类型(自己还是对方) + content + "$$$$$$$$" //消息字符串 msg + "empty"; //图片服务器地址 且不带http前缀 et_text.setText(""); webSocketClient.send(con); //刷新chatListAdapter myTalkBean = new ChatHistoryBean.TalkDataListBean(); myTalkBean.time = sdf.format(date_time); myTalkBean.user_id = SpUtils.getUserId(activity); myTalkBean.user_name = SpUtils.getUserName(activity); myTalkBean.user_image = SpUtils.getHeadimg(activity).split("files/")[1]; myTalkBean.link_user_id = link_user_id; myTalkBean.link_user_name = link_user_name; myTalkBean.link_user_image = link_user_image; myTalkBean.type = "0"; myTalkBean.text = content; myTalkBean.image = "empty"; datas.add(myTalkBean); chatListAdapter.notifyDataSetChanged(); recycleview.scrollToPosition(datas.size() - 1); } }); } /** * 改变标题栏 * * @param title */ private void changeTitle(final String title) { runOnUiThread(new Runnable() { @Override public void run() { tv_title.setText(title); } }); } @Override protected void onDestroy() { webSocketClient.close(); super.onDestroy(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 101 && resultCode == RESULT_OK) { // 从相册返回的数据 String img_path = data.getStringExtra(SelectPicActivity.KEY_PHOTO_PATH); Log.i(TAG, "最终选择的图片1=" + img_path); BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(img_path, opts); //先显示错误图片 ,图片上传完之后再显示正确图片 myTalkBean_img = new ChatHistoryBean.TalkDataListBean(); myTalkBean_img.time = sdf.format(date_time); myTalkBean_img.user_id = SpUtils.getUserId(activity); myTalkBean_img.user_name = SpUtils.getUserName(activity); myTalkBean_img.user_image = SpUtils.getHeadimg(activity).split("files/")[1]; myTalkBean_img.link_user_id = link_user_id; myTalkBean_img.link_user_name = link_user_name; myTalkBean_img.link_user_image = link_user_image; myTalkBean_img.type = "0"; myTalkBean_img.text = "empty"; myTalkBean_img.image = "img"; datas.add(myTalkBean_img); chatListAdapter.notifyDataSetChanged(); recycleview.scrollToPosition(datas.size() - 1); UploadFilesUtil.upLoadFile(img_path, new MyString2Callback() { @Override public void onError(Call call, Exception e) { ToastUtils.showToast("上传失败"); } @Override public void onResponse(Call call, String s) { // waitDialog.dismiss(); UploadResultBean resultBean = new Gson().fromJson(s, UploadResultBean.class); if (resultBean.code == 0) { //上传成功 String imgHttpPath = resultBean.message;//没有前缀http的服务器图片地址 String con = SpUtils.getUserId(activity) + "$$$$$$$$" //自己的id + SpUtils.getUserName(activity) + "$$$$$$$$" //自己的昵称 + SpUtils.getHeadimg(activity).split("files/")[1] + "$$$$$$$$" //自己的头像 + link_user_id + "$$$$$$$$" //对方id + link_user_name + "$$$$$$$$" //对放昵称 + link_user_image + "$$$$$$$$" //对方头像 + "0" + "$$$$$$$$" //消息类型(自己还是对方) + "empty" + "$$$$$$$$" //消息字符串 msg + imgHttpPath; //图片服务器地址 且不带http前缀 // et_text.clearComposingText(); webSocketClient.send(con); myTalkBean_img.image = imgHttpPath; chatListAdapter.notifyDataSetChanged(); recycleview.scrollToPosition(datas.size() - 1); } else { ToastUtils.showToast(activity.getResources().getString(R.string.result_upload_error)); } } }); // 如果图片还没有回收,强制回收,防止OOM异常 if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); System.gc(); } } } /** * 获取单个人的聊天历史记录 * * @param link_uid */ private void onLoadToGetSomeBodyChatHistory(String link_uid) { String uid = SpUtils.getUserId(activity); ServiceApi.getSomeBodyChatHistory(isMailChat, uid, link_uid, new MyString2Callback() { @Override public void onError(Call call, Exception e) { ToastUtils.showInternetErrorToast(); } @Override public void onResponse(Call call, String s) { Log.d(TAG, "onResponse() returned: " + s); Type type = new TypeToken<ArrayList<ChatHistoryBean>>() { }.getType(); List<ChatHistoryBean> dataBean = new Gson().fromJson(s, type); if (dataBean != null && dataBean.size() != 0) { datas = dataBean.get(0).talkDataList; if (datas != null && datas.size() != 0) { chatListAdapter = new ChatListAdapter(activity, datas); recycleview.setAdapter(chatListAdapter); if (datas.size() != 0) { recycleview.scrollToPosition(datas.size() - 1); } } } else { chatListAdapter = new ChatListAdapter(activity, datas); recycleview.setAdapter(chatListAdapter); } } }); } }
我们分析下这里的主要方法。
1.首先要添加WebSocket 的依赖,不然谁让你用啊。
compile 'org.java-websocket:Java-WebSocket:1.3.0'
2.看initData();这里初始化WebSocket :initWebSocketClient();
@Override protected void initData() { // tv_title.setText("连接中..."); if (isMailChat) { rl_titlebar.setBackgroundColor(getResources().getColor(R.color.titlebar_bg_blue)); } else { rl_titlebar.setBackgroundColor(getResources().getColor(R.color.titlebar_bg)); } chatListAdapter = new ChatListAdapter(activity, datas);//聊天列表 initWebSocketClient();//初始化webSocket chatBean = (ChatHistoryBean) getIntent().getSerializableExtra("bean"); if (chatBean == null) { //如果为null,表示不是从聊天历史记录中跳转过来的,而是从其他页面点击"联系我们"跳转进来的 link_user_id = getIntent().getStringExtra("link_id"); link_user_name = getIntent().getStringExtra("link_user_name"); link_user_image = getIntent().getStringExtra("link_user_image"); //获取单个人的聊天历史记录 onLoadToGetSomeBodyChatHistory(link_user_id); } else { link_user_id = chatBean.link_user_id; link_user_name = chatBean.link_user_name; link_user_image = chatBean.link_user_image; datas = chatBean.talkDataList; chatListAdapter = new ChatListAdapter(activity, datas); recycleview.setAdapter(chatListAdapter); if (datas.size() != 0) { recycleview.scrollToPosition(datas.size() - 1); } } }
方法initWebSocketClient();初始化WebSocket
/** * 初始化websocket */ private void initWebSocketClient() { URI uri = null; try { if (isMailChat) {//员工聊天websocket的连接地址 uri = new URI(NetUtils.WS_CHAT_MAIL + SpUtils.getUserId(activity)); } else {//业务聊天websocket的连接地址 uri = new URI(NetUtils.WS_CHAT_BUSINESS + SpUtils.getUserId(activity)); } } catch (Exception e) { e.printStackTrace(); } //连接中使用的new Draft_17()就是使用的协议version 17(RFC 6455),Tomcat 7.0使用的协议版本为RFC 6455。 Draft_17 draft = new Draft_17(); webSocketClient = new WebSocketClient(uri, draft) { @Override//连接成功 public void onOpen(ServerHandshake handshakedata) { Log.d(TAG, "run() returned: " + "连接到服务器"); String title = getIntent().getStringExtra("title"); changeTitle(title); } @Override//从服务端消息(聊天时对方发过来的消息) public void onMessage(final String message) { Log.d(TAG, "run() returned: " + message); // 8735$$$$$$$$nature$$$$$$$$a0/51/97/a051979545fa49f18444fc7b2d8f6477.png$$$$$$$$8678$$$$$$$$anan$$$$$$$$db/cd/97/dbcd979f580049ae8cb6f0cbf5969f70.png$$$$$$$$0$$$$$$$$Zzzzz$$$$$$$$empty // 字符串$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$字符串 用$$$$$$$$分割 // /****自己的id**自己的昵称**自己的头像***对方id***对放昵称**对方头像****消息类型(自己还是对方)****消息字符串****图片****/ runOnUiThread(new Runnable() { @Override public void run() { try { String messages[] = message.split("\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024");//$$$$$$$$分割 myTalkBean = new ChatHistoryBean.TalkDataListBean(); myTalkBean.user_id = messages[0]; myTalkBean.user_name = messages[1]; myTalkBean.user_image = messages[2]; myTalkBean.link_user_id = messages[3]; myTalkBean.link_user_name = messages[4]; myTalkBean.link_user_image = messages[5]; myTalkBean.type = "1"; myTalkBean.text = messages[7]; myTalkBean.image = messages[8]; myTalkBean.time = sdf.format(date_time); datas.add(myTalkBean); chatListAdapter.notifyDataSetChanged(); recycleview.smoothScrollToPosition(datas.size() - 1); } catch (Exception e) { e.printStackTrace(); } } }); }
这里参考下文献:http://blog.csdn.net/tangxl2008008/article/details/52421413
这里有四个方法,要格外注意:
onOpen():方法是链接成功是调用。
onMessage();方法是从服务端消息(聊天时对方发过来的消息),这里显示的内容对方发过来的内容。
@Override//从服务端消息(聊天时对方发过来的消息) public void onMessage(final String message) { Log.d(TAG, "run() returned: " + message); // 8735$$$$$$$$nature$$$$$$$$a0/51/97/a051979545fa49f18444fc7b2d8f6477.png$$$$$$$$8678$$$$$$$$anan$$$$$$$$db/cd/97/dbcd979f580049ae8cb6f0cbf5969f70.png$$$$$$$$0$$$$$$$$Zzzzz$$$$$$$$empty // 字符串$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$字符串 用$$$$$$$$分割 // /****自己的id**自己的昵称**自己的头像***对方id***对放昵称**对方头像****消息类型(自己还是对方)****消息字符串****图片****/ runOnUiThread(new Runnable() { @Override public void run() { try { String messages[] = message.split("\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024\\u0024");//$$$$$$$$分割 myTalkBean = new ChatHistoryBean.TalkDataListBean(); myTalkBean.user_id = messages[0]; myTalkBean.user_name = messages[1]; myTalkBean.user_image = messages[2]; myTalkBean.link_user_id = messages[3]; myTalkBean.link_user_name = messages[4]; myTalkBean.link_user_image = messages[5]; myTalkBean.type = "1"; myTalkBean.text = messages[7]; myTalkBean.image = messages[8]; myTalkBean.time = sdf.format(date_time); datas.add(myTalkBean); chatListAdapter.notifyDataSetChanged(); recycleview.smoothScrollToPosition(datas.size() - 1); } catch (Exception e) { e.printStackT b0c5 race(); } } }); }获取到内容后要刷新Adapter,才能显示。
onClose();连接断开,remote判定是客户端断开还是服务端断开
onError();链接错误。
但是不要忘记加上:webSocketClient.connect(); 才能链接到WebSocket.
接下来看是如何发送消息的:
/** * 发送文本消息 */ private void sendMessage() { //字符串$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$%@$$$$$$$$字符串 用$$$$$$$$分割 // /****自己的id**自己的昵称**自己的头像***对方id***对放昵称**对方头像****消息类型(自己还是对方)****消息字符串****图片****/ String img; content = et_text.getEditableText().toString(); if (StringUtils.isEmpty(content)) { content = "empty"; return; } else { img = "empty"; } runOnUiThread(new Runnable() { @Override public void run() {//webSocketClient发送的文字消息,不是图片 String con = SpUtils.getUserId(activity) + "$$$$$$$$" //自己的id + SpUtils.getUserName(activity) + "$$$$$$$$" //自己的昵称 + SpUtils.getHeadimg(activity).split("files/")[1] + "$$$$$$$$" //自己的头像 + link_user_id + "$$$$$$$$" //对方id + link_user_name + "$$$$$$$$" //对放昵称 + link_user_image + "$$$$$$$$" //对方头像 + "0" + "$$$$$$$$" //消息类型(自己还是对方) + content + "$$$$$$$$" //消息字符串 msg + "empty"; //图片服务器地址 且不带http前缀 et_text.setText(""); webSocketClient.send(con); } }); }webSocketClient.send(con);是发送消息所用,发送的内容。这里发送消息只是发送到后台并没有及时的去更新我们的消息列表,怎么办呢?
//刷新chatListAdapter myTalkBean = new ChatHistoryBean.TalkDataListBean(); myTalkBean.time = sdf.format(date_time); myTalkBean.user_id = SpUtils.getUserId(activity); myTalkBean.user_name = SpUtils.getUserName(activity); myTalkBean.user_image = SpUtils.getHeadimg(activity).split("files/")[1]; myTalkBean.link_user_id = link_user_id; myTalkBean.link_user_name = link_user_name; myTalkBean.link_user_image = link_user_image; myTalkBean.type = "0"; myTalkBean.text = content; myTalkBean.image = "empty"; datas.add(myTalkBean); chatListAdapter.notifyDataSetChanged(); recycleview.scrollToPosition(datas.size() - 1);我们手动去给bean赋值,是我们发送的内容,然后刷新Adapter。这样我们就能完成文字聊天了。
还有一个方法:
recycleview.smoothScrollToPosition(datas.size() - 1);想必都很好奇,既然已经刷新过了还调用他干嘛,哈哈哈。。。 我们看下效果图你就明白了
这是添加recycleview.smoothScrollToPosition(datas.size() - 1); 的效果;
大家看到当每收到一条消息后都会显示出来。
这是没有添加这句的效果:
大家看下就能发现问题。列表刷新后我们并没有立即看到,还有向上滑动才显示内容。
我们再看下图片的发送,这里推按只能发送一张每次,首先是上传图片,然后是为Bean赋值,刷新Adapter,这里离我急不介绍了。
不过有一点还要注意,
// 如果图片还没有回收,强制回收,防止OOM异常 if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); System.gc(); }强制回收,防止OOM.
当我们销毁页面时:WebSocket断开连接。
@Override protected void onDestroy() { webSocketClient.close(); super.onDestroy(); }
相关文章推荐
- 使用Netty进行Android与Server端通信实现文字发送接收与图片上传
- 使用Netty进行Android与Server端通信实现文字发送接收与图片上传
- android 轻松实现在线即时聊天【图片、语音、表情、文字】等!含源码!
- Android图片滚动,加入自动播放功能,使用自定义属性实现,霸气十足!
- Android实现分享图片和文字的功能
- Android 使用ViewPager结合PhotoView开源组件实现网络图片在线浏览功能
- Android实现新浪微博SSO授权登录分享文字图片等功能
- Android中使用Service实现后台发送邮件功能实例
- Android系统自带分享功能的实现(可同时分享文字和图片)
- Android系统自带分享功能的实现(可同时分享文字和图片)
- Android Intent分享文件|分享图片|分享文字|功能的实现
- Android实现分享图片和文字的功能
- android 轻松实现在线即时聊天【图片、语音、表情、文字】等!含源码!
- Android图片滚动,加入自动播放功能,使用自定义属性实现,霸气十足!
- Android使用ViewPager、PhotoView实现类似QQ空间图片浏览功能
- Android使用PhotoView实现图片缩放功能
- Android图片滚动,加入自动播放功能,使用自定义属性实现,霸气十足!
- Android图片滚动,加入自动播放功能,使用自定义属性实现,霸气十足!
- Android系统自带分享功能的实现(可同时分享文字和图片)
- Android实现新浪微博SSO授权登录分享文字图片等功能(WEIBO_ANDROID_SDK V2.3.0 )