Android 通过WebSocket实现IM功能那些坑

前不久在项目中实现了Im功能,之前im功能使用使用第三方,这次用到了WebSocket。找到

https://github.com/TooTallNate/Java-WebSocket

compile "org.java-websocket:Java-WebSocket:1.3.7"

基于库实现过程遇到不少问题:


坑1:WebSocketClient objects are not reuseable

  new WebSocketClient对象只能连接一次(调用connect时),要重新建立得再new 一次。

  网络好的情况下,websoket会经常断开,重新连接,但要连接过程中又要考虑正在聊天的内容,不能让用户正在聊天感觉断网了,连接成功后把聊天的内容发送出去,所以要做一个聊天数据缓冲区。


坑2:发送的信息没有反馈是否送达?

首先要理解WebSocket是”心跳“机制,会”假“连接中状态,一但发送信息就会走onClose,信息则未发送到服务器;

WebSocketClient中有三个抽象方法:

	public abstract void onOpen( ServerHandshake handshakedata );
	public abstract void onMessage( String message );
	public abstract void onClose( int code, String reason, boolean remote );
	public abstract void onError( Exception ex );
	public void onMessage( ByteBuffer bytes ) {
		//To overwrite
	}

一但发送信息时WebSocketClient.send( String text ),会在约200毫秒内回调onClose方法,则断定刚发送的信息不成功。我是设定发送出去后1秒内未走onclose则断定已发送出去。未发送成功则放在数据缓冲区,等连接成功后再把缓冲的数据再发送一次,当然缓冲区的每个数据都有个加入时间,超过一定时间后又未发送出去(断网)则反馈给UI知并更新db。


坑3:表情图

  表情是使用[mj00]代表, 点击表情显示到输入框上:

		gvMoji.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView parent, View view, int position, long id) {
				String emji = mMojiHAdapter.getItem(position);
				int reId = getResources().getIdentifier(emji, "drawable", getPackageName());
				emji = "[" + emji + "]";
				SpannableString spannableString = new SpannableString(emji);
				ImageSpan imageSpan = new ImageSpan(ImHActivity.this, reId);
				spannableString.setSpan(imageSpan, 0, emji.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
				int index = edtWrit.getSelectionStart();
				Editable editable = edtWrit.getText();
				editable.insert(index, spannableString);
			}
		});

聊天列表内容的转换(正则):

	public static void setText(TextView tv, String content) {
		tv.setText("");
		if (null != content) {
			Pattern pattern = Pattern.compile("\\[[^\\[\\]]*\\]");
			Matcher matcher = pattern.matcher(content);
			int start = -1;
			int end = -1;
			while (matcher.find()) {
				start = matcher.start();

				if (end != -1 && start > end) {
					tv.append(content.substring(end, start));
				}
				if (start != 0 && end == -1) {
					tv.append(content.substring(0, start));
				}

				end = matcher.end();
				String emji = content.substring(start + 1, end - 1);
				int reId = tv.getContext().getResources().getIdentifier(emji, "drawable",
						tv.getContext().getPackageName());
				if (reId == 0) { // 配对了,但不是表情
					tv.append(content.substring(start, end));
				} else {
					emji = content.substring(start, end);
					SpannableString spannableString = new SpannableString(emji);
					ImageSpan imageSpan = new ImageSpan(tv.getContext(), reId);
					spannableString.setSpan(imageSpan, 0, emji.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
					tv.append(spannableString);
				}
			}

			if (end == -1) {
				tv.setText(content);
			} else if (end != content.length()) {
				tv.append(content.substring(end, content.length()));
			}
		}
	}

其他小坑:

聊天列表

   聊天有6种类型(ViewTypeCount),文字、语音、图片(发送与接收各三种)

   坑在数据库没设计好,重构了二次表,因为需求说自己可以跟自己聊天。

聊天图片要处理在微信一样有个角:

Android 通过WebSocket实现IM功能那些坑_第1张图片Android 通过WebSocket实现IM功能那些坑_第2张图片

代码实现合成 右图是ninePicId:

	private Bitmap getPic(Bitmap bitmap_in, int ninePicId) {
		Bitmap bitmap_bg = BitmapFactory.decodeResource(context.getResources(), ninePicId);

		Bitmap roundConcerImage = Bitmap.createBitmap(bitmap_in.getWidth(), bitmap_in.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(roundConcerImage);
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
		Rect dst = new Rect(0, 0, bitmap_in.getWidth(), bitmap_in.getHeight());
		Rect src = new Rect(0, 0, bitmap_in.getWidth(), bitmap_in.getHeight());
		paint.setAntiAlias(true);
		NinePatch patch = new NinePatch(bitmap_bg, bitmap_bg.getNinePatchChunk(), null);
		patch.draw(canvas, dst);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap_in, src, dst, paint);

		return roundConcerImage;
	}



compile "org.java-websocket:Java-WebSocket:1.3.7"

你可能感兴趣的:(android_problem)