7.xmpp版即时聊天
即时聊天的解决方案
- socket:
- xmpp:xmpp+openfire+asmack
- 环信
常见协议


比较安全,tcp上还加了俩层

简单聊一下socket
socket:套接字,连接需要ip和端口,分为tcp和udp两种形式
常见的术语
- xmpp:基于xml的可拓展协议.
- jabber:xmpp的前身.
- openfire:支持xmpp的开源服务器
- smack.jar:对xmpp协议封装.方便开发的jar包.
- spark.exe:基于xmpp的pc客户端;
- asmack.jar:smack.jar的精简版.专门针对android端开发

xmpp的认识.
- xmpp官网:http://xmpp.org/
- XMPP(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。
xmpp特点:
- 开放: XMPP协议是自由、开放、公开的,并且易于了解。 而且在客户端 、 服务器 、 组件 、 源码库等方面,都已经各自有多种实现。
- 标准: 互联网工程工作小组( IETF )已经将Jabber的核心XML流协议以XMPP之名,正式列为认可的实时通信及Presence技术。 而XMPP的技术规格已被定义在RFC3920及RFC3921 。 任何IM供应商在遵循XMPP协议下,都可与Google Talk实现连接。
- 证实可用: 第一个Jabber(现在XMPP)技术是Jeremie Miller在1998年开发的,现在已经相当稳定;数以百计的开发者为XMPP技术而努力。 今日的互联网上有数以万计的XMPP服务器运作着,并有数以百万计的人们使用XMPP实时传讯软件。
- 分散式: XMPP网络的架构和电子邮件十分相像;XMPP核心协议通信方式是先创建一个stream,XMPP以TCP传递XML数据流,没有中央主服务器。 任何人都可以运行自己的XMPP服务器,使个人及组织能够掌控他们的实时传讯体验。
- 安全: 任何XMPP协议的服务器可以独立于公众XMPP网络(例如在企业内部网络中),而使用SASL及TLS等技术的可靠安全性,已自带于核心XMPP技术规格中。
- 可扩展: XML 命名空间的威力可使任何人在核心协议的基础上建造定制化的功能;为了维持通透性,常见的扩展由XMPP标准基金会 。 弹性佳 XMPP除了可用在实时通信的应用程序,还能用在网络管理、内容供稿、协同工具、文件共享、游戏、远程系统监控等。
- 多样性: 用XMPP协议来建造及布署实时应用程序及服务的公司及开放源代码计划分布在各种领域;用XMPP技术开发软件,资源及支持的来源是多样的,使得使你不会陷于被“绑架”的困境。
相关的下载
asmack github:https://github.com/Flowdalic/asmack
asmack下载地址1:http://asmack.freakempire.de/
asmack下载地址2:http://code.google.com/p/asmack/downloads/list
openfire下载地址:http://www.igniterealtime.org/downloads/index.jsp
smack使用指南:http://www.igniterealtime.org/builds/smack/docs/latest/documentation/index.html
openfire的安装
- 官网
http://www.igniterealtime.org/ - 安装包的类型
- exe安装包-->点击exe根据提示安装
- zip包解压版-->解压放到指定目录就可以了.
- 首次运行的配置
- 配置语言-->
中文简体 - 配置数据库形式-->
内嵌数据库 - 配置服务器名称-->
itheima - 配置管理员账号密码-->
admin admin。帐号就是这个,没有@xxx那些
- 配置语言-->
- 创建用户
- admin admin
- hm1 111111
spark的安装-->xmpp客户端1
- 直接下一步就可以完成
- 运行
- 1.配置服务器ip
- 2.输入用户账号/密码
如意通的安装-->xmpp客户端2
pc端-服务器-pc端演示
smack常见api的查看.
xmpp版即使聊天的核心:其实就是熟悉asmack.jar里面的一些常见类.以及常见监听器;
工程搭建
- asmack.jar的下载,下载地址
http://asmack.freakempire.de/ - 创建android工程.
- 添加jar包.添加依赖
- as关联源码.
引导页模块splashActivity
ThreadUtils的封装.
public class ThreadUtils {
/**
* 子线程执行task
*/
public static void runInThread(Runnable task) {
new Thread(task).start();
}
/**
* 创建一个主线程中handler
*/
public static Handler mHandler = new Handler();
/**
* UI线程执行task
*/
public static void runInUIThread(Runnable task) {
mHandler.post(task);
}
}
public class {
/**
* 可以在子线程中弹出toast
*
* @param context
* @param text
*/
public static void showToastSafe(final Context context, final String text) {
ThreadUtils.runInUIThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
});
}
}
public class SplashActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
// 停留3s,进入登录界面
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
// 休眠3s
SystemClock.sleep(3000);
// 进入主界面
Intent intent = new Intent(SplashActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
});
}
}
登录模块LoginActivity
- 引入了
ButterKnife.jar以及as的android-butterknife-zelezny插件 - ButterKnife:类似xutils中的viewUtils,可以注解的框架,图为关联源码,点右面
- 调用api登录
连接配置
// 设置常见的参数 config.setDebuggerEnabled(true);// 开启调试模式,可以看到传输的xml config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);//明文传输
public class LoginActivity extends ActionBarActivity {
public static final String HOST = "192.168.1.100"; // 主机ip
public static final int PORT = 5222; // 对应的端口号
public static final String SERVICENAME = "itheima.com";
private TextView mEtUserName;
private TextView mEtPassWord;
private Button mBtnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView();
initListener();
}
private void initListener() {
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String userName = mEtUserName.getText().toString();
final String passWord = mEtPassWord.getText().toString();
// 判断用户名是否为空
if (TextUtils.isEmpty(userName)) {// 用户名为空,系统自带的textview的属性,弹出悬浮窗提示
mEtUserName.setError("用户名不能为空");
return;
}
// 判断密码是否为空
if (TextUtils.isEmpty(passWord)) {// 用户名为空
mEtPassWord.setError("密码不能为空");
return;
}
ThreadUtils.runInThread(new Runnable() {
@Override
public void run() {
try {
// 1.创建连接配置对象
ConnectionConfiguration config = new ConnectionConfiguration(HOST, PORT);
// 额外的配置(方面我们开发,上线的时候,可以改回来)
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);// 明文传输
config.setDebuggerEnabled(true);// 开启调试模式,方便我们查看具体发送的内容
// 2.开始创建连接对象
XMPPConnection conn = new XMPPConnection(config);
// 开始连接
conn.connect();
// 连接成功了
// 3.开始登录
conn.login(userName, passWord);
// 已经成功成功
ToastUtils.showToastSafe(LoginActivity.this, "登录成功");
finish();
// 跳到主界面
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
// 需要保存连接对象
IMService.conn = conn;
//启动IMService
Intent service = new Intent(LoginActivity.this, IMService.class);
startService(service);
} catch (XMPPException e) {
e.printStackTrace();
ToastUtils.showToastSafe(LoginActivity.this, "登录失败");
}
}
});
}
});
}
private void initView() {
mEtUserName = (TextView) findViewById(R.id.et_username);
mEtPassWord = (TextView) findViewById(R.id.et_password);
mBtnLogin = (Button) findViewById(R.id.btn_login);
}
}
主页面MainActivity
ToolBarUtil
public class ToolBarUtil {
private List<TextView> mTextViews = new ArrayList<TextView>();
public void createToolBar(LinearLayout container, String[] toolBarTitleArr, int[] iconArr) {
for (int i = 0; i < toolBarTitleArr.length; i++) {
TextView tv = (TextView) View.inflate(container.getContext(), R.layout.inflate_toolbar_btn, null);
tv.setText(toolBarTitleArr[i]);
// 动态修改textView里面的drawableTop属性
tv.setCompoundDrawablesWithIntrinsicBounds(0, iconArr[i], 0, 0);
int width = 0;
int height = LinearLayout.LayoutParams.MATCH_PARENT;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height);
//设置weight属性
params.weight = 1;
container.addView(tv, params);
//保存textView到集合中
mTextViews.add(tv);
//设置点击事件
final int finalI = i;
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//不同模块之间传值需要用接口回调
//3.需要传值的地方.用接口对象调用接口方法
mOnToolBarClickListener.onToolBarClick(finalI);
}
});
}
}
public void changeColor(int position) {
//还原所有的颜色
for (TextView tv : mTextViews) {
tv.setSelected(false);
}
mTextViews.get(position).setSelected(true);//通过设置selected属性,控制为选中效果
}
//1.创建接口和接口方法
public interface OnToolBarClickListener{
void onToolBarClick(int position);
}
//2.定义接口变量
OnToolBarClickListener mOnToolBarClickListener;
//4.暴露一个公共的方法
public void setOnToolBarClickListener(OnToolBarClickListener onToolBarClickListener) {
mOnToolBarClickListener = onToolBarClickListener;
}
}
public class MainActivity extends ActionBarActivity {
@InjectView(R.id.main_tv_title)
TextView mMainTvTitle;
@InjectView(R.id.main_viewpager)
ViewPager mMainViewpager;
@InjectView(R.id.main_bottom)
LinearLayout mMainBottom;
// xutils viewutils 注解方式去找控件
// viewutils httpUitls dbutils bitmaputils
//
private List<Fragment> mFragments = new ArrayList<Fragment>();
private ToolBarUtil mToolBarUtil;
private String[] mToolBarTitleArr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
initData();
initListener();
}
private void initListener() {
mMainViewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// 修改颜色
mToolBarUtil.changeColor(position);
// 修改title
mMainTvTitle.setText(mToolBarTitleArr[position]);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
mToolBarUtil.setOnToolBarClickListener(new ToolBarUtil.OnToolBarClickListener() {
@Override
public void onToolBarClick(int position) {
mMainViewpager.setCurrentItem(position);
}
});
}
private void initData() {
// viewPager-->view-->pagerAdapter
// viewPager-->fragment-->fragmentPagerAdapter-->fragment数量比较少
// viewPager-->fragment-->fragmentStatePagerAdapter
// 添加fragment到集合中
mFragments.add(new SessionFragment());
mFragments.add(new ContactsFragment());
mMainViewpager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
// 底部按钮
mToolBarUtil = new ToolBarUtil();
// 文字内容
mToolBarTitleArr = new String[] { "会话", "联系人" };
// 图标内容
int[] iconArr = { R.drawable.selector_meassage, R.drawable.selector_selfinfo };
mToolBarUtil.createToolBar(mMainBottom, mToolBarTitleArr, iconArr);
// 设置默认选中会话
mToolBarUtil.changeColor(0);
}
class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return 2;
}
}
}
7.xmpp版即时聊天的更多相关文章
- Asp.Net Mvc基于Fleck开发的多人网页版即时聊天室
一.项目的核心说明 1.Fleck这个是实现websocket一个比较简单第三方组件,它不需要安装额外的容器.本身也就几个接口可供调用. 2.项目是基于.net framework 4.7.2 ,在v ...
- 即时聊天IM之三 XMPP协议客户端库的和Android端框架概述
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com smack ...
- 即时聊天 / XMPP
MQTT是第二个即时聊天协议(了解) 5.即时通讯 即时通讯网上有第三方的解决方案,比如环信,融云等.我们是自己搭的xmpp服务器,服务器使用的tigase,之前写过相关的博客,自己去年也做了对应的w ...
- 几款web版整合(QQ、msn、icq、yahoo通、Gtalk等)即时聊天http://hi.baidu.com/ejie/blog/item/e89794ef9a9431efce1b3ebd.html
直到近期为止,我们经常使用的即时聊天工具(QQ.msn等)了Web版,大家不用下载庞大软件,直接打开网页就能够与自己的好友聊天,很方便.在此将时汇总,便于大家查找,节约大家一点时间. 此都是官 ...
- iOS:XMPP即时聊天知识
XMPP即时聊天框架:XMPPFramework XMPP The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). 基于XML XM ...
- XMPP环境搭建 (mac环境下 安装自己独立的mysql与服务器(openfire),实现即时聊天功能)
1简单概览 [一]XMPP简介 http://xmpp.org 即时通讯技术 IM - Instant Messaging ⽀支持⽤用户在线实时交谈.交谈双⽅方都需要⼀一个聊天窗⼝口,其中⼀一个⽤用户 ...
- Android基于xmpp的即时通讯应用
xmpp是一个通信协议.因为这是个开放的协议,为了节俭开发成本,很多即时应用都采用了这个协议.Android上最常用的组合asmack +openfire.Asmack是smack的android版, ...
- 即时聊天IM之二 openfire 整合现有系统用户
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com 综述: ...
- 类似QQ的应用毗邻(Pilin)即时聊天源码
这个应用是从安卓教程网分享过了的,个人觉得这个还是挺不错的,毗邻(Pilin)即时聊天应用源码,承诺的 基于xmpp openfire asmack 的即时聊天应用,继续完善,现在只完成了文字.表 ...
随机推荐
- ASP.NET MVC学习笔记-----使用自定义的View Engine
我们都知道在ASP.NET MVC中自带了Razor View Engine,Razor十分的强大,可以满足我们绝大部分的需要.但是ASP.NET MVC的高度可扩展性,使我们可以使用自定义的View ...
- Matlab之字符串处理
Matlab处理字符串 1.取得部分字符串 我们有一个字符串 file='20131030_113109.TemporaryAlias.Poly5'; 简单操作举例: >> a=file( ...
- Flume-NG内置计数器(监控)源码级分析
Flume的内置监控怎么整?这个问题有很多人问.目前了解到的信息是可以使用Cloudera Manager.Ganglia有图形的监控工具,以及从浏览器获取json串,或者自定义向其他监控系统汇报信息 ...
- Asteroids(匈牙利算法入门)
Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16211 Accepted: 8819 Descri ...
- userdate和table类型的效率对比
做cocos2d-x开发的人可能有不少人在实现类时会利用cocos2d-x自己给出的类的实现,也即在luaBinding目录下extern.lua的文件中给出的实现: --Create an clas ...
- HDU 1062 Text Reverse(水题,字符串处理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1062 解题报告:注意一行的末尾可能是空格,还有记得getchar()吃回车符. #include< ...
- ios中的category与extension
http://blog.csdn.net/haishu_zheng/article/details/12873151 category和extension用来做类扩展的,可以对现有类扩展功能或者修 ...
- Nginx反向代理的目录访问问题
Nginx反向代理的目录访问问题 2013-05-13 23:21 2730人阅读 评论(0) 收藏 举报 从昨天就开始纠结了,在做实验的时候,遇到目录访问的问题,如下 前端nginx vhost的设 ...
- net发送邮件
对于.NET而言,从2.0开始,发邮件已经是一件非常easy 的事了.下面我给出一个用C#群发邮件的实例,做了比较详细的注解,希望对有需要的朋友有所help.看了这篇BLOG,如果你还不会用.NET发 ...
- TokuDB的特点验证
随着数据量越来越大,越来越频繁的遇到需要进行结构拆分的情况,每一次拆分都耗时很久,并且需要多方配合,非常的不想搞这个事情.于是在@zolker的提醒下想到了13年开源tokuDB,来解决我们迫在眉睫的 ...