Android 高仿微信实时聊天 基于百度云推送

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:【张鸿洋的博客】

一直在仿微信界面,今天终于有幸利用百度云推送仿一仿微信聊天了~~~

首先特别感谢:weidi1989分享的Android之基于百度云推送IM ,大家可以直接下载;省了很多事哈,本例中也使用了weidi的部分代码,凡是@author way的就是weidi1989的代码~~

1、效果图

核心功能也就上面的两张图了~~~我拿着手机和模拟器聊天,同时感谢群里的兄弟姐妹帮忙测试(好友列表中)。

2、原理

下面通过几个问题来说明下实现的原理:

1、如何实现给某个用户发送消息呢?

其实就是利用百度云提供的REST API,直接通过发送Http请求的形式给某个用户推送一条消息;

网址:http://developer.baidu.com/wiki/index.php?title=docs/cplat/push/api/list

实例:

push_msg
功能
推送消息,该接口可用于推送单个人、一群人、所有人以及固定设备的使用场景。
HTTP请求方式
POST
URL
http[s]://channel.api.duapp.com/rest/2.0/channel/channel

....

2、的确可以实现给某个用户或者一群用户推送消息,那么用户的昵称神马的咋获取的呢,我印象中百度云中没法存这样的数据?

嗯,其实用了一个比较巧妙的方式;在用户首次安装软件的时候,会要求用户填写注册信息,也就是昵称等;当用户填写完毕时,点击登录的时候:

1、发送一条比较特殊的消息,比如这个消息携带一个hello的字段,广播给所有用户;

2、其他用户在收到消息时,首先判断hello这个字段是否有值,有值则说明新用户加入,把该新用户存入本地数据库,然后更新用户列表;

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);

			return true;
		}

		return false;
	}

当收到一个新的消息:

1、首先判断是不是自己发的,是,忽略;

2、判断是否携带hello字段,代表新人加入,携带,则保存到好友列表,且回复一个携带welcome字段的消息;

3、判断是否包含welcome字段,包含,存入好友列表

4、不是1、2、3则肯定是普通消息,将消息保存到本地数据库,然后为所有设置消息监听的发送回调即可~

MainTabFriends.java用户列表中收到新消息的回调:

/**
	 * 收到新消息时
	 */
	@Override
	public void onNewMessage(Message message)
	{
		// 如果是自己发送的,则直接返回
		if (message.getUserId() == mSpUtils.getUserId())
			return;
		// 如果该用户已经有未读消息,更新未读消息的个数,并通知更新未读消息接口,最后notifyDataSetChanged
		String userId = message.getUserId();
		if (mUserMessages.containsKey(userId))
		{
			mUserMessages.put(userId, mUserMessages.get(userId) + 1);
		} else
		{
			mUserMessages.put(userId, 1);
		}
		mUnReadedMsgs++;
		notifyUnReadedMsg();
		// 将新来的消息进行存储
		ChatMessage chatMessage = new ChatMessage(message.getMessage(), true,
				userId, message.getHeadIcon(), message.getNickname(), false,
				TimeUtil.getTime(message.getTimeSamp()));
		mApplication.getMessageDB().add(userId, chatMessage);
		// 通知listview数据改变
		mAdapter.notifyDataSetChanged();
	}

1、如果是自己发的不做任何处理

2、如果当前消息发送用户已有未读消息,则更新该用户未读消息个数(用户Item上显示未读消息通知数),更新所有未读消息总和(朋友Tab上显示未读消息总和),然后存储该消息

3、刷新界面

ChattingActivity.java聊天界面的新消息回调

@Override
	public void onNewMessage(Message message)
	{

		// 获得回复的消息
		if (mFromUser.getUserId().equals(message.getUserId()))
		{
			ChatMessage chatMessage = new ChatMessage();
			chatMessage.setComing(true);
			chatMessage.setDate(new Date(message.getTimeSamp()));
			chatMessage.setMessage(message.getMessage());
			chatMessage.setUserId(message.getUserId());
			chatMessage.setNickname(message.getNickname());
			chatMessage.setReaded(true);
			mDatas.add(chatMessage);
			mAdapter.notifyDataSetChanged();
			mChatMessagesListView.setSelection(mDatas.size() - 1);
			// 存入数据库,当前聊天记录
			mApplication.getMessageDB().add(mFromUser.getUserId(), chatMessage);
		}
	}

首先判断是否是正在聊天的用户发的消息,如果是,直接存入数据库,刷新聊天界面;

好了,细节也不展开描述了,大家自己看源码,bug肯定有,发现bug可以直接留言,方便其他学习的童鞋,也方便我了,多谢~~~~~~~~~~~~~~

ps:最近状态不好,我要去喝脉动~~~~

源码点击下载 大家可以先安装压缩文件里面的apk测试下,这样就可以发现别的伙伴了~~~

时间: 2024-08-02 06:57:35

Android 高仿微信实时聊天 基于百度云推送的相关文章

基于百度云推送的高仿微信实时聊天Android源码

基于百度云推送的高仿微信实时聊天Android源码 使用服务:百度云推送    功能分类:社交     支持平台:Android 运行环境:Android       开发语言:Java     开发工具:Eclipse 下载地址:http://sina.lt/z84 源码简介 基于百度云推送的一款Android高仿微信的实时聊天app 运行动态图

Android第十三期 - 百度云推送(百度后台版)

这回比较费事儿,我给学弟学妹分解一下,下面开始: 配置部分: 1.去百度云推送注册账号,配置一下,如图: 2.点击消息跳转的配置部分,如图: 3.发送消息的配置,如图: 这样就完成百度后台的发送消息的服务器的配置了. 接着是App的代码部分: 1.MyPushMessageReceiver:  package com.baidu.push.example; import java.text.SimpleDateFormat; import java.util.Date; import java.

Android项目集成百度云推送,无法回调到PushMessageReceiver中onBind方法的问题与解决

今天准备集成百度云推送,因为据朋友说,百度云推送作为android的推送还是相对稳定的. 开发工具:android studio 1.2.1.1  系统:Mac os x 10.10.3 立即下载了最新的V4.4.1版本的百度云推送demo,仔仔细细按照文档一步一步做完.但是测试的时候,就是回调不了. 最后在百度云应用管理详情中,看见了“生成快速示例的按钮”,生成之后安装,发现可以正常使用.于是开始研究这个快速示例,最后发现只有一处不同:armeabi/libbdpush_V2_2.so和mip

Android使用第三方推送(二)百度云推送

时间过得好快,转眼就是12月了.工作了之后,发现节奏停不下来,像是被上了发条,再也由不得自己.工作日如流水,周末更是转瞬即逝.其实想想也是有时间的,只不过没有很好的利用,或者花在了没有意义的事情上面.人总是有惰性的,但是持续下去就不好了. 上周开始接触第三方云推送,先后体验了极光推送,个推和百度云推送,也感受了各个平台的特性.有的部署便捷,有的功能强大,有的稳定可靠.今天简单介绍一下百度云推送的使用. 百度云推送给我的感觉就是稳定可靠,毕竟是百度出品,值得信赖.而且富媒体推送也是免费,又胜出极光

消息推送之百度云推送Android集成与使用方法

这两天由于项目需要,研究了一下百度云推送,本来这事没什么多大工作量的,但注册百度开发者账户创建应用令我蛋疼菊紧了好一阵,这些东西做了对技术没啥提升,不做又不行,必经之路.好在我耗费了N多个毫毫秒秒后稀里哗啦的闯了过来. 在此先吐槽一下.这个云推送虽然没多少东西,但对于初次接触的人来说还是有点不利索的,所以肯定要看官方文档,只是不知是百度哪个哥们做的文档,pdf做的也太不地体贴了:英文字符里面竟然有中文空格,复制到自己的项目中发现江山一片红,娘的,这猛一看还不一定能看得出来到底是哪里出了错. fo

消息推送之百度云推送Android集成与用法

这两天因为项目须要.研究了一下百度云推送,本来这事没什么多大工作量的,但注冊百度开发人员账户创建应用令我蛋疼菊紧了好一阵,这些东西做了对技术没啥提升,不做又不行,必经之路. 好在我耗费了N多个毫毫秒秒后稀里哗啦的闯了过来. 在此先吐槽一下.这个云推送尽管没多少东西,但对于初次接触的人来说还是有点不利索的,所以肯定要看官方文档.仅仅是不知是百度哪个哥们做的文档.pdf做的也太不地体贴了:英文字符里面居然有中文空格,拷贝到自己的项目中发现江山一片红,娘的.这猛一看还不一定能看得出来究竟是哪里出了错.

Android源码之百度云推送

使用服务:百度云推送   功能分类:工具            开发工具:Eclipse 支持平台:Android      运行环境:Android       开发语言:Java 下载地址:http://www.devstore.cn/code/info/184.html 源码简介 百度云推送官方Demo,默认编码UTF-8 .导入项目后将AndroidManifest.xml 104行处 api_key 字段值修改为自己的 api_key 方可使用 ! 源码运行截图

Android推送 百度云推送 入门篇

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27231237 现在app基本都有推送的功能,于是看了下百度云的推送,官方文档和Demo都很到位,记录下使用过程,目标是利用百度云推送最为服务器写个及时通讯的例子~当然了,这是第一篇入门~ 1.第一步就是在百度开发者服务管理中创建项目,然后拿到API key , Secret Key ;这个过程就不多说了,上官网直接申请就行,不复杂. 2.下载云推送的客户端SDK,SDK的压缩文

【源码分享下载】每日更新之Android源码之百度云推送

Android源码之百度云推送 支持平台:Android      运行环境:Android       开发语言:Java 下载地址:http://www.devstore.cn/code/info/184.html 源码简介 百度云推送官方Demo,默认编码UTF-8 .导入项目后将AndroidManifest.xml 104行处 api_key 字段值修改为自己的 api_key 方可使用 !! 源码运行截图