三十二:基于XMPP聊天会议室(2)

      上一篇已经得到了所有创建的房间,今天就进入房间聊两句,不过要先看一下smack文档的MultiUserChat类(多用户聊天),官方文档是这么说的:

      A MultiUserChat is a conversation that takes place among many users in a virtual room. A room could have many occupants with different affiliation and roles. Possible affiliatons are "owner", "admin", "member", and "outcast". Possible roles are "moderator", "participant", and "visitor". Each role and affiliation guarantees different privileges (e.g. Send messages to all occupants, Kick participants and visitors, Grant voice, Edit member list, etc.).

      我大致翻译一下:

     MultiUserChat是在一个虚拟的房间里发生在很多用户之间的交流,一个房间可能有很多不同归属和角色的群体,可能归属是“所有者”,”管理员“,”成员“,”被踢的人“。可能角色是”主持人“,”参与者“,”访客“。每个角色和归属保证不同的特权(例如.发送消息给所有人,踢参与者和游客,授予说话权限,编辑成员列表,等等)。

1、文档里有一个构造方法和很多其他的方法,我就不说了,有空可以看一下,由于时间关系,直接进入代码:

2、先看xml文件,activity_roomchat.xml,一个ListView,editText,Button没什么说的。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/lv_roomMsg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/et_sendRoomMsg"
        android:layout_alignParentLeft="true"
        android:divider="@null" >
    </ListView>

    <EditText
        android:id="@+id/et_sendRoomMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@+id/btn_sendRoomMsg"
        android:ems="10"
        android:hint="@string/roomchat_hint" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/btn_sendRoomMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="@string/chat_sendMsg" />

</RelativeLayout>
3、RoomChatActivity.java代码,是主要代码,可以看一下Smack文档和我的注释,其实和单聊的监听差不多。在创建房间的时候如果你写了密码,那么我这里弹出一个dialog,去输入密码,成功就进入。这里我就判断了一下401错误,其实还有很多,像402,403,404等等,有空你们可以研究一下都是什么错误,这里我就不说了。

package org.hkby.lwx.activity;

import java.util.ArrayList;
import java.util.List;

import org.hkby.lwx.adapter.RoomChatAdapter;
import org.hkby.lwx.common.RoomMsg;
import org.hkby.lwx.common.SystemTime;
import org.hkby.lwx.common.XmppTool;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.muc.MultiUserChat;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
/**
 * room chat
 * @author liaowuxing
 *
 */
public class RoomChatActivity extends Activity {
	private MultiUserChat muc;
	private EditText et_sendRoomMsg;
	private Button btn_send;
	private String jid;

	private ListView lv_roomMsg;
	private List<RoomMsg> listMsg = new ArrayList<RoomMsg>();
	private RoomChatAdapter adapter;
	private String loginUser;
	
	private AlertDialog dialog;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_roomchat);
		getData();
		initView();
		initClick();
	}

	private void getData(){
		//get JID
		jid = getIntent().getStringExtra("jid");
		// instantiate MultiUserChat
		muc = new MultiUserChat(XmppTool.getConnection(), jid);
		//get login username
		SharedPreferences sp = getSharedPreferences("username",Activity.MODE_PRIVATE);
		loginUser = sp.getString("account", "");
		try {
			// Join a chat room
			muc.join(loginUser);
			Log.v("---TAG", "join success");
		} catch (XMPPException e) {
			e.printStackTrace();
			int code = e.getXMPPError().getCode();
			if (code == 401) {
				//if code is 401,Need a password
				showDialog(loginUser, muc);
			}else {
				finish();
			}
		}
	}
	public void initView() {
		lv_roomMsg = (ListView) this.findViewById(R.id.lv_roomMsg);
		et_sendRoomMsg = (EditText) this.findViewById(R.id.et_sendRoomMsg);
		btn_send = (Button) this.findViewById(R.id.btn_sendRoomMsg);
		adapter = new RoomChatAdapter(RoomChatActivity.this, listMsg);
		lv_roomMsg.setAdapter(adapter);
	}

	public void initClick() {
		// Listen to the message
		muc.addMessageListener(new PacketListener() {
			@Override
			public void processPacket(Packet packet) {
				Message message = (Message) packet;
				Log.v("---MSG", "--from:" + message.getFrom() + "--body:" + message.getBody());
				android.os.Message m = handler.obtainMessage();
				m.obj = message;
				m.sendToTarget();
			}
		});
		// send message
		btn_send.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String roomMsg = et_sendRoomMsg.getText().toString();
				try {
					if (roomMsg == "" || roomMsg.length() == 0) {
						Toast.makeText(RoomChatActivity.this, R.string.roomMsgIsEmpty, Toast.LENGTH_SHORT).show();
					}else {
						muc.sendMessage(roomMsg);
					}
				} catch (XMPPException e) {
					e.printStackTrace();
				}
				//clear editText
				et_sendRoomMsg.setText("");
			}
		});
	}

	/**
	 * Receives the message
	 */
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			Message m = new Message();
			m = (Message) msg.obj;
			String username = m.getFrom().toString().split("/")[1];
			String body = m.getBody();
			if (username.equals(loginUser)) {
				RoomMsg sendRoomMsg = new RoomMsg(loginUser, body,
						SystemTime.getDate(), "to");
				listMsg.add(sendRoomMsg);
				adapter.notifyDataSetChanged();
			} else {
				RoomMsg roomMsg = new RoomMsg(username, body,
						SystemTime.getDate(), "from");
				listMsg.add(roomMsg);
				adapter.notifyDataSetChanged();
			}
		};
	};
	/**
	 * show dialog
	 * @param loginUser
	 * @param muc
	 */
	public void showDialog(final String loginUser,final MultiUserChat muc){
		AlertDialog.Builder builder = new AlertDialog.Builder(RoomChatActivity.this);
		builder.setInverseBackgroundForced(true);
		View view = LayoutInflater.from(RoomChatActivity.this).inflate(
				R.layout.joinroom_item, null);
		final EditText et_password = (EditText) view
				.findViewById(R.id.et_password);
		Button btn_login = (Button) view.findViewById(R.id.btn_join);
		btn_login.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				String password = et_password.getText().toString();
				if (password != null && password.length() != 0) {
					dialog.dismiss();
					try {
						muc.join(loginUser, password);
					} catch (XMPPException e) {
						e.printStackTrace();
						int code = e.getXMPPError().getCode();
						if (code == 401) {
							Toast.makeText(RoomChatActivity.this, R.string.passwordError, Toast.LENGTH_SHORT).show();
							// password is error
							finish();
						}else {
							finish();
						}
					}
				} else {
					Toast.makeText(RoomChatActivity.this, R.string.PasswordNotEmpty,
							Toast.LENGTH_SHORT).show();
				}
			}
		});
		Button btn_cancle = (Button) view.findViewById(R.id.btn_cancle);
		btn_cancle.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				dialog.dismiss();
				finish();
			}
		});
		builder.setView(view);
		dialog = builder.create();
		dialog.show();
	}
}

4、这里和单聊一样我同样建了一个类RoomMsg.java:

package org.hkby.lwx.common;


/**
 * room message
 * @author liaowuxing
 *
 */
public class RoomMsg {


	public String username;
	public String msg;
	public String date;
	public String fromorto;


	public RoomMsg(String username, String msg, String date,String fromorto) {
		this.username = username;
		this.msg = msg;
		this.date = date;
		this.fromorto = fromorto;
	}
}

5、adapter代码,RoomChatAdapter.java:

package org.hkby.lwx.adapter;

import java.util.List;

import org.hkby.lwx.activity.R;
import org.hkby.lwx.common.RoomMsg;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
/**
 * adapter
 * @author liaowuxing
 *
 */
public class RoomChatAdapter extends BaseAdapter {
	private List<RoomMsg> listMsg;
	private Context context;
	private LayoutInflater mInflater;
	public RoomChatAdapter(Context context,List<RoomMsg> listMsg) {
		super();
		this.context = context;
		this.listMsg = listMsg;
		mInflater = LayoutInflater.from(context);
	}

	@Override
	public int getCount() {
		return listMsg.size();
	}

	@Override
	public Object getItem(int position) {
		return listMsg.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (listMsg.get(position).fromorto.equals("from")) {
			ViewHolder viewHolder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.roomchart_from_item, null);
			viewHolder.tv_roomName = (TextView)convertView.findViewById(R.id.tv_from_roomName);
			viewHolder.tv_roomDate = (TextView)convertView.findViewById(R.id.tv_from_roomDate);
			viewHolder.tv_roomMsg = (TextView)convertView.findViewById(R.id.tv_from_roomMsg);
			convertView.setTag(viewHolder);
		}else {
			ViewHolder viewHolder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.roomchat_to_item, null);
			viewHolder.tv_roomName = (TextView)convertView.findViewById(R.id.tv_to_roomName);
			viewHolder.tv_roomDate = (TextView)convertView.findViewById(R.id.tv_to_roomDate);
			viewHolder.tv_roomMsg = (TextView)convertView.findViewById(R.id.tv_to_roomMsg);
			convertView.setTag(viewHolder);
		}
		ViewHolder vHolder = (ViewHolder) convertView.getTag();
		//message
		String msg = listMsg.get(position).msg;
		if (msg == null) {
			vHolder.tv_roomMsg.setText("");
		}else {
			vHolder.tv_roomMsg.setText(msg);
		}
		//date
		String date = listMsg.get(position).date;
		if (msg == null) {
			vHolder.tv_roomDate.setText("");
		}else {
			vHolder.tv_roomDate.setText(date);
		}
		//username
		String name = listMsg.get(position).username;
		if (msg == null) {
			vHolder.tv_roomName.setText("");
		}else {
			vHolder.tv_roomName.setText(name);
		}
		return convertView;
	}

	private class ViewHolder{
		private TextView tv_roomName;
		private TextView tv_roomDate;
		private TextView tv_roomMsg;
	}
}

6、adapter里同样有两个布局,一个roomchart_from_item.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_from_roomName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:textColor="#ff0000"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_from_roomDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/tv_from_roomName" />

    <LinearLayout
        android:id="@+id/ll_from_room"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/tv_from_roomName"
        android:layout_marginBottom="5sp"
        android:layout_marginLeft="10sp"
        android:background="@drawable/roomchart_from_bg" >

        <TextView
            android:id="@+id/tv_from_roomMsg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>

7、一个roomchat_to_item.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_to_roomName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:textColor="#0000ff"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_to_roomDate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/tv_to_roomName" />

    <LinearLayout
        android:id="@+id/ll_to_room"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/tv_to_roomName"
        android:layout_marginBottom="5sp"
        android:layout_marginLeft="10sp"
        android:background="@drawable/roomchart_tobg" >

        <TextView
            android:id="@+id/tv_to_roomMsg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>

8、dialog布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_showMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_password"
        android:layout_alignParentTop="true"
        android:layout_marginTop="18dp"
        android:text="@string/tv_showMsg"
        android:textColor="#ff0000" />

    <TextView
        android:id="@+id/tv_password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/et_password"
        android:layout_alignLeft="@+id/btn_join"
        android:text="@string/roomPassword"
        android:textSize="16sp" />

    <EditText
        android:id="@+id/et_password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/tv_showMsg"
        android:layout_marginTop="24dp"
        android:layout_toRightOf="@+id/tv_password"
        android:ems="10"
        android:hint="@string/et_inputPassword"
        android:inputType="textPassword" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/btn_join"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/et_password"
        android:layout_marginLeft="10sp"
        android:layout_marginTop="20sp"
        android:text="@string/btn_join" />

    <Button
        android:id="@+id/btn_cancle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@+id/btn_join"
        android:text="@string/btn_cancle" />

</RelativeLayout>

9、string.xml代码:

 <!-- 聊天室 -->
    <string name="createRoom">创建房间</string>
    <string name="roomchat_hint">请输入内容</string>
    <string name="roomMsgIsEmpty">消息不能为空</string>
    <string name="roomPassword">密码:</string>
    <string name="btn_join">加入</string>
    <string name="btn_cancle">取消</string>
    <string name="tv_showMsg">本聊天室需要密码进入</string>
    <string name="et_inputPassword">请输入密码</string>
    <string name="PasswordNotEmpty">密码不能为空</string>
    <string name="passwordError">密码错误</string>

10、代码写完了,看一下工程结构:



11、聊天效果图:


12、ok,今天就到这了,哈哈偷笑


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值