版权说明:本文是基于开源LumaQQ下,开发者不直接参与QQ协议的分析工作,移植到Android平台纯粹是为了方便学习和研究之用,并且没有产生任何直接的经济效益,并且纯粹是个人的技术学习研究行为,与本人所在单位没有任何关系。此文的读者在使用过程产生的效益和涉及的法律责任与本人没有直接关系。如果影响到您或您的公司利益,敬请谅解并且与我联系,本人会第一时间作出处理。
我们继续Lumaqq的移植旅程。今天将设计一个比较复杂的界面,来深入了解Android的UI设计。
登录成功之后,我们就可以向QQ服务器发出各种请求,例如得到好友列表,得到分组信息,系统消息什么的。这方面Lumaqq给我们提供了很大的便利性,他把各种复杂的网络请求,分析数据包给封装了起来,例如请求好友列表可以使用QQClient类的user_GetList(),然后通过QQEvent的事件QQEvent.FRIEND_GET_LIST_OK就可以方便的得到好友列表信息了。
Android的程序设计有两个关键概念,一个称为Activity,一个称为Intent。一个应用程序可能由一组Activities组成,之间的通信请求通过Intent传递。每一个Activity代表一个用户所能看到的屏幕。这方面的知识网上有很多,看SDK也能很好的理解,程序员杂志在08年1月刊也有文章来介绍,我就不多说什么废话啦。
我们现在的Lumaqq由两个Activity组成,一个是QQLogin,它功能是提供登录界面。作为Sub Activity,由主Activity启动调用。另一个是主Activity,功能是提供系统菜单,处理各种QQEnent,显示好友列表。
- QQLogin类
- public class QQLogin extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- findViews();
- setListeners();
- }
- private Button button_test;
- private EditText field_qqID;
- private EditText field_qqPwd;
- private void findViews() {
- button_test = (Button) findViewById(R.id.submit);
- field_qqID = (EditText) findViewById(R.id.qqID);
- field_qqPwd = (EditText) findViewById(R.id.qqPwd);
- }
- private void setListeners() {
- button_test.setOnClickListener(testLumaQQ);
- }
- private OnClickListener testLumaQQ = new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- // Bundle数据容器类,类似于key/value键值对,但比之更强大
- Bundle myBundle = new Bundle();
- myBundle.putInt("qqNum", Util.getInt(field_qqID.getText().toString(), -1));
- myBundle.putString("qqPwd", field_qqPwd.getText().toString());
- Intent mIntent = new Intent();
- mIntent.putExtras(myBundle);
- setResult(RESULT_OK, mIntent);
- finish();
- }
- };
- }
主Activity lumaqqMe,我们的主Activity继承自ListActivity,这个提供了一个ListView和一些函数,让我们很方便的添加一个列表进去。
- public class lumaqqMe extends ListActivity implements IQQListener {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.list);
- //设置系统菜单
- getListView().setOnCreateContextMenuListener(this);
- //初始化
- initialize();
- }
- private QQClient client;
- private String resultStr;
- private List<String> UserList;
- //Sub Activity Code
- private static final int ACTIVITY_LOGIN = 1000;
- //菜单ID
- public static final int LOGIN_ID = Menu.FIRST;
- public static final int EXIT_ID = Menu.FIRST + 1;
- private void initialize() {
- client = new QQClient();
- resultStr = "";
- UserList = new ArrayList<String>();
- }
- //检查登录,如果已登录就返回
- private void checkLogin(int qq, String pwd) {
- if (client.isLogging())
- return;
- client.setConnectionPoolFactory(new PortGateFactory());
- QQUser user = new QQUser(qq, pwd);
- // 设置参数
- client.addQQListener(this);
- user.setUdp(true);
- client.setUser(user);
- client.setLoginServer("sz.tencent.com");
- try {
- // 登录
- client.login();
- } catch (Exception e1) {
- }
- }
- @Override
- public void qqEvent(QQEvent e) {
- // TODO Auto-generated method stub
- switch (e.type) {
- case QQEvent.LOGIN_OK:
- processLoginSuccess();
- break;
- case QQEvent.LOGIN_FAIL:
- processLoginFail(e);
- break;
- case QQEvent.LOGIN_UNKNOWN_ERROR:
- processLoginUnknownError();
- break;
- case QQEvent.IM_SEND_OK:
- processSendIMSuccess();
- break;
- case QQEvent.USER_STATUS_CHANGE_OK:
- processChangeStatusSuccess();
- break;
- case QQEvent.USER_STATUS_CHANGE_FAIL:
- processChangeStatusFail();
- break;
- case QQEvent.SYS_TIMEOUT:
- switch (e.operation) {
- case QQ.QQ_CMD_GET_FRIEND_LIST:
- processGetFriendListTimeout(e);
- case QQ.QQ_CMD_SEND_IM:
- processSendIMFail();
- }
- break;
- case QQEvent.FRIEND_GET_LIST_OK:
- processGetFriendListSuccess(e);
- break;
- }
- }
- /**
- * 处理得到好友列表超时事件,我们简单得重发超时的包
- *
- * @param e
- * QQEvent
- */
- private void processGetFriendListTimeout(QQEvent e) {
- client.sendPacket((OutPacket) e.getSource());
- }
- /**
- * 初始改变状态失败事件
- */
- private void processChangeStatusFail() {
- resultStr = getText(R.string.message_box_status_change_fail).toString();
- handler.sendEmptyMessage(0);
- client.logout();
- client.release();
- }
- /**
- * 处理改变状态成功事件
- */
- private void processChangeStatusSuccess() {
- resultStr = getText(R.string.message_box_status_change_ok).toString();
- handler.sendEmptyMessage(0);
- //请求好友列表
- client.user_GetList();
- }
- /**
- * 处理发送消息失败事件
- */
- private void processSendIMFail() {
- resultStr = getText(R.string.message_box_sys_timeout).toString();
- handler.sendEmptyMessage(0);
- client.logout();
- client.release();
- }
- /**
- * 处理发送消息成功事件
- */
- private void processSendIMSuccess() {
- resultStr = getText(R.string.message_box_send_ok).toString();
- handler.sendEmptyMessage(0);
- client.logout();
- client.release();
- }
- /**
- * 处理登陆成功事件
- */
- private void processLoginSuccess() {
- if (!client.getUser().isLoggedIn()) {
- resultStr = getText(R.string.message_box_login_success).toString();
- handler.sendEmptyMessage(0);
- }
- }
- /**
- * 处理登陆密码错误事件
- *
- * @param e
- */
- private void processLoginFail(QQEvent e) {
- resultStr = getText(R.string.message_box_login_fail).toString();
- handler.sendEmptyMessage(0);
- }
- /**
- * 处理登陆未知错误事件
- */
- private void processLoginUnknownError() {
- resultStr = getText(R.string.message_box_unknown_error).toString();
- handler.sendEmptyMessage(0);
- }
- /**
- * 处理得到好友列表成功事件
- */
- private void processGetFriendListSuccess(QQEvent e) {
- GetFriendListReplyPacket packet = (GetFriendListReplyPacket)e.getSource();
- for (QQFriend friend : packet.friends) {
- UserList.add(friend.nick);
- }
- // 如果是得到好友列表结束事件,返回
- if (packet.position == QQ.QQ_POSITION_FRIEND_LIST_END) {
- handler1.sendEmptyMessage(0);
- } else
- client.user_GetList(packet.position);
- }
- private Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- new AlertDialog.Builder(lumaqqMe.this).setPositiveButton("ok",
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // TODO Auto-generated method stub
- }
- }).setMessage(resultStr).show();
- super.handleMessage(msg);
- }
- };
- private Handler handler1 = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(
- lumaqqMe.this, android.R.layout.simple_list_item_1,
- UserList);
- setListAdapter(adapter);
- super.handleMessage(msg);
- }
- };
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // TODO Auto-generated method stub
- super.onActivityResult(requestCode, resultCode, data);
- Bundle bundle = data.getExtras();
- if (requestCode == ACTIVITY_LOGIN) {
- if (resultCode == RESULT_OK) {
- int qqnum = bundle.getInt("qqNum");
- String qqpwd = bundle.getString("qqPwd");
- checkLogin(qqnum, qqpwd);
- }
- }
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // TODO Auto-generated method stub
- boolean result = super.onCreateOptionsMenu(menu);
- menu.add(0, LOGIN_ID, 0, R.string.menu_login);
- menu.add(0, EXIT_ID, 0, R.string.menu_exit);
- return result;
- }
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- // TODO Auto-generated method stub
- switch (item.getItemId()) {
- case LOGIN_ID:
- startActivityForResult(new Intent(this, QQLogin.class),
- ACTIVITY_LOGIN);
- return true;
- case EXIT_ID:
- client.logout();
- client.release();
- finish();
- return true;
- }
- return super.onMenuItemSelected(featureId, item);
- }
- }
让我们来看看界面大概什么样吧。
主界面
登录界面
登录成功之后得到好友列表