Android 高仿微信实时聊天 基于百度云推送,Android开发中遇到最难的问题

88 阅读3分钟

3、其他用户给这个新用户回一条消息,附带一个特殊字段,比如welcome,当新用户收到携带welcome字段的消息时,表明这是对新用户hello的答复,然后将已存在用户添加到该新用户的用户列表。

基本原理就这样了,大家甚至可以利用上述的原理添加一些删除好友的功能;比如当用户点击删除好友,则发送一条特殊消息给被删除的对象,然后对方收到该消息,也将发送发删除。

相信大家在了解原理之后,这个例子瞬间从高大尚变成矮矬穷了,这尼玛,so easy,谁不会啊~~~

3、核心代码解析

========

由于代码量还是相当大的,也不想拆成几篇博客,所以准备将核心代码进行讲解下,其他的大家自己看源码~

关于这个例子的主界面,可以参考: 高仿微信5.2.1主界面架构 包含消息通知

关于百度云推送的入门,可以参考:Android推送 百度云推送 入门篇

好了,最主要就是收到百度云推送的Receiver

1、onBind


首先是用户第一次登录时候绑定的回调

@Override

public void onBind(final Context context, int errorCode, String appid,

String userId, String channelId, String requestId)

{

String responseString = "onBind errorCode=" + errorCode + " appid="

  • appid + " userId=" + userId + " channelId=" + channelId

  • " requestId=" + requestId;

Log.e(TAG, responseString);

if (errorCode == 0)

{

SharePreferenceUtil util = PushApplication.getInstance()

.getSpUtil();

util.setAppId(appid);

util.setChannelId(channelId);

util.setUserId(userId);

} else

// 如果网络正常,则重试

{

if (NetUtil.isNetConnected(context))

{

T.showLong(context, "启动失败,正在重试...");

new Handler().postDelayed(new Runnable()

{

@Override

public void run()

{

PushManager.startWork(context,

PushConstants.LOGIN_TYPE_API_KEY,

PushApplication.API_KEY);

}

}, 2000);// 两秒后重新开始验证

} else

{

T.showLong(context, R.string.net_error_tip);

}

}

// 回调函数

for (int i = 0; i < bindListeners.size(); i++)

bindListeners.get(i).onBind(userId, errorCode);

}

初次绑定的时候,如果绑定成功则使用SharedPreferences存储userId,channelId等数据

然后回调:bindListeners.get(i).onBind(userId, errorCode);给所有注册该事件的发出通知

下面看listener.onBind

/**

  • 收到通知

*/

@Override

public void onBind(String userId, int errorCode)

{

Log.e("TAG", "Login Activity onBind ");

if (errorCode == 0)

{

Log.e("TAG", "Login Activity onBind success ");

// 如果绑定账号成功,由于第一次运行,给同一tag的人推送一条新人消息

User u = new User(mSpUtil.getUserId(), mSpUtil.getChannelId(),

mSpUtil.getNick(), mSpUtil.getHeadIcon(), 0);

mUserDB.addUser(u);// 把自己添加到数据库

Message firstSendMsg = new Message(System.currentTimeMillis(), "");

firstSendMsg.setHello("hello");

task = new SendMsgAsyncTask(mGson.toJson(firstSendMsg), "");

task.setOnSendScuessListener(new OnSendScuessListener()

{

@Override

public void sendScuess()

{

if (mLoadingDialog != null && mLoadingDialog.isVisible())

mLoadingDialog.dismiss();

mHandler.removeCallbacks(mConnTimeoutCallback);

finish();

Intent intent = new Intent(LoginActivity.this,

MainActivity.class);

startActivity(intent);

}

});

task.send();

}

}

首先将自己保存到本地数据库,然后发送一个Message给所有的用户,设置一个特殊字段hello;也就是上述的原理分析中的部分~

2、onMessage


收到百度云推送的Receiver中的onMessage

@Override

public void onMessage(Context context, String message,

String customContentString)

{

String messageString = "收到消息 message="" + message

  • "" customContentString=" + customContentString;

Log.e(TAG, messageString);

Message receivedMsg = PushApplication.getInstance().getGson()

.fromJson(message, Message.class);

// 对接收到的消息进行处理

parseMessage(receivedMsg);

}

/**

  • 消息:1、携带hello,表示新人加入,应该自动回复一个world 消息; 2、普通消息;

  • @param msg

*/

private void parseMessage(Message msg)

{

String userId = msg.getUserId();

// 自己的消息

if (userId

.equals(PushApplication.getInstance().getSpUtil().getUserId()))

return;

if (checkHasNewFriend(msg) || checkAutoResponse(msg))

return;

// 普通消息

UserDB userDB = PushApplication.getInstance().getUserDB();

User user = userDB.selectInfo(userId);

// 漏网之鱼

if (user == null)

{

user = new User(userId, msg.getChannelId(), msg.getNickname(), 0, 0);

userDB.addUser(user);

// 通知监听的面板

for (onNewFriendListener listener : friendListeners)

listener.onNewFriend(user);

}

if (msgListeners.size() > 0)

{// 有监听的时候,传递下去

for (int i = 0; i < msgListeners.size(); i++)

msgListeners.get(i).onNewMessage(msg);

} else

// 当前没有任何监听,即处理后台状态

{

// 将新来的消息进行存储

ChatMessage chatMessage = new ChatMessage(msg.getMessage(), true,

userId, msg.getHeadIcon(), msg.getNickname(), false,

TimeUtil.getTime(msg.getTimeSamp()));

PushApplication.getInstance().getMessageDB()

.add(userId, chatMessage);

showNotify(msg);

}

}

/**

  • 检测是否是自动回复

  • @param msg

*/

private boolean checkAutoResponse(Message msg)

{

String world = msg.getWorld();

String userId = msg.getUserId();

if (!TextUtils.isEmpty(world))

{

User u = new User(userId, msg.getChannelId(), msg.getNickname(),

msg.getHeadIcon(), 0);

PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友

// 通知监听的面板

for (onNewFriendListener listener : friendListeners)

listener.onNewFriend(u);

return true;

}

return false;

}

/**

  • 检测是否是新人加入

  • @param msg

*/

private boolean checkHasNewFriend(Message msg)

{

String userId = msg.getUserId();

String hello = msg.getHello();

// 新人发送的消息

if (!TextUtils.isEmpty(hello))

{

Log.e("checkHasNewFriend", msg.getUserId());

// 新人

User u = new User(userId, msg.getChannelId(), msg.getNickname(),

msg.getHeadIcon(), 0);

PushApplication.getInstance().getUserDB().addUser(u);// 存入或更新好友

T.showShort(PushApplication.getInstance(), u.getNick() + "加入");

// 给新人回复一个应答

Message message = new Message(System.currentTimeMillis(), "");

message.setWorld("world");

new SendMsgAsyncTask(PushApplication.getInstance().getGson()

.toJson(message), userId);

// 通知监听的面板

for (onNewFriendListener listener : friendListeners)

listener.onNewFriend(u);

总结

【Android 详细知识点思维脑图(技能树)】

image

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

详细整理在GitHub:Android架构视频+BAT面试专题PDF+学习笔记​

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。