即时聊天的解决方案

  • 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特点:

  1. 开放: XMPP协议是自由、开放、公开的,并且易于了解。 而且在客户端 、 服务器 、 组件 、 源码库等方面,都已经各自有多种实现。
  2. 标准: 互联网工程工作小组( IETF )已经将Jabber的核心XML流协议以XMPP之名,正式列为认可的实时通信及Presence技术。 而XMPP的技术规格已被定义在RFC3920及RFC3921 。 任何IM供应商在遵循XMPP协议下,都可与Google Talk实现连接。
  3. 证实可用: 第一个Jabber(现在XMPP)技术是Jeremie Miller在1998年开发的,现在已经相当稳定;数以百计的开发者为XMPP技术而努力。 今日的互联网上有数以万计的XMPP服务器运作着,并有数以百万计的人们使用XMPP实时传讯软件。
  4. 分散式: XMPP网络的架构和电子邮件十分相像;XMPP核心协议通信方式是先创建一个stream,XMPP以TCP传递XML数据流,没有中央主服务器。 任何人都可以运行自己的XMPP服务器,使个人及组织能够掌控他们的实时传讯体验。
  5. 安全: 任何XMPP协议的服务器可以独立于公众XMPP网络(例如在企业内部网络中),而使用SASL及TLS等技术的可靠安全性,已自带于核心XMPP技术规格中。
  6. 可扩展: XML 命名空间的威力可使任何人在核心协议的基础上建造定制化的功能;为了维持通透性,常见的扩展由XMPP标准基金会 。 弹性佳 XMPP除了可用在实时通信的应用程序,还能用在网络管理、内容供稿、协同工具、文件共享、游戏、远程系统监控等。
  7. 多样性: 用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的安装

  1. 官网http://www.igniterealtime.org/
  2. 安装包的类型
    1. exe安装包-->点击exe根据提示安装
    2. zip包解压版-->解压放到指定目录就可以了.
  3. 首次运行的配置
    1. 配置语言-->中文简体
    2. 配置数据库形式-->内嵌数据库
    3. 配置服务器名称-->itheima
    4. 配置管理员账号密码-->admin admin。帐号就是这个,没有@xxx那些
  4. 创建用户
    1. admin admin
    2. hm1 111111

spark的安装-->xmpp客户端1

  • 直接下一步就可以完成
  • 运行
    • 1.配置服务器ip
    • 2.输入用户账号/密码

如意通的安装-->xmpp客户端2

pc端-服务器-pc端演示

smack常见api的查看.

xmpp版即使聊天的核心:其实就是熟悉asmack.jar里面的一些常见类.以及常见监听器;

工程搭建

  1. asmack.jar的下载,下载地址http://asmack.freakempire.de/
  2. 创建android工程.
  3. 添加jar包.添加依赖
  4. 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();
            }
        });
    }
}
 
 
 
SplashActivity
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

  1. 引入了ButterKnife.jar以及as的android-butterknife-zelezny插件
  2. ButterKnife:类似xutils中的viewUtils,可以注解的框架,图为关联源码,点右面
  3. 调用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;
    }
}

  

 
MainActivity
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版即时聊天的更多相关文章

  1. Asp.Net Mvc基于Fleck开发的多人网页版即时聊天室

    一.项目的核心说明 1.Fleck这个是实现websocket一个比较简单第三方组件,它不需要安装额外的容器.本身也就几个接口可供调用. 2.项目是基于.net framework 4.7.2 ,在v ...

  2. 即时聊天IM之三 XMPP协议客户端库的和Android端框架概述

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com smack ...

  3. 即时聊天 / XMPP

    MQTT是第二个即时聊天协议(了解) 5.即时通讯 即时通讯网上有第三方的解决方案,比如环信,融云等.我们是自己搭的xmpp服务器,服务器使用的tigase,之前写过相关的博客,自己去年也做了对应的w ...

  4. 几款web版整合(QQ、msn、icq、yahoo通、Gtalk等)即时聊天http://hi.baidu.com/ejie/blog/item/e89794ef9a9431efce1b3ebd.html

        直到近期为止,我们经常使用的即时聊天工具(QQ.msn等)了Web版,大家不用下载庞大软件,直接打开网页就能够与自己的好友聊天,很方便.在此将时汇总,便于大家查找,节约大家一点时间. 此都是官 ...

  5. iOS:XMPP即时聊天知识

    XMPP即时聊天框架:XMPPFramework   XMPP The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). 基于XML XM ...

  6. XMPP环境搭建 (mac环境下 安装自己独立的mysql与服务器(openfire),实现即时聊天功能)

    1简单概览 [一]XMPP简介 http://xmpp.org 即时通讯技术 IM - Instant Messaging ⽀支持⽤用户在线实时交谈.交谈双⽅方都需要⼀一个聊天窗⼝口,其中⼀一个⽤用户 ...

  7. Android基于xmpp的即时通讯应用

    xmpp是一个通信协议.因为这是个开放的协议,为了节俭开发成本,很多即时应用都采用了这个协议.Android上最常用的组合asmack +openfire.Asmack是smack的android版, ...

  8. 即时聊天IM之二 openfire 整合现有系统用户

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com  综述: ...

  9. 类似QQ的应用毗邻(Pilin)即时聊天源码

      这个应用是从安卓教程网分享过了的,个人觉得这个还是挺不错的,毗邻(Pilin)即时聊天应用源码,承诺的 基于xmpp openfire asmack 的即时聊天应用,继续完善,现在只完成了文字.表 ...

随机推荐

  1. 编译安装apache下添加mod_rewrite支持

    今天我依旧在学习我的编程语言,接到同事的一个请求.说在25*服务器上添加一个apache的mod_rewrite的模块支持 感觉还好了,这个很简单,所有就开始做了.不过这个服务器已经相当久远了,一下吧 ...

  2. 再谈对协变和逆变的理解(Updated)

    去年写过一篇博客谈了下我自己对协变和逆变的理解,现在回头看发现当时还是太过“肤浅”,根本没理解.不久前还写过一篇“黑”Java泛型的博客,猛一回头又是“肤浅”,今天学习Java泛型的时候又看到了协变和 ...

  3. 你真的会用AsyncTask吗?(一)

    一个典型AsyncTask的. view source print? 01 public class DialogTestActivity extends Activity { 02     priv ...

  4. Win10走红背后,最开心的人却是谷歌

    导读 微软在不惜余力推进Windows10普及的同时,也有一些让自己小小郁闷的事儿发生,在Win10系统当中,微软用新的Edge浏览器取代了用户熟悉的IE浏览器,以求改写在浏览器市场上的被动局面,不过 ...

  5. yum 配置

    1.配置yum本地源 # mount /dev/cdrom /mnt/ # vim /etc/yum.repos.d/rhel-source.repo 1 [rhel-source] 2 name=R ...

  6. 学习jquery mobile

    学习jquery mobile的时间不是很长,在学习的过程当中也遇到了很多令人抓狂的问题,在网上搜索问题答案的时候发现,现在关于jquery mobile的文章还不是很多,所以,我也是一边学习,一边摸 ...

  7. 【转】maven命令背后是如何工作的

    转载自:http://yinny.iteye.com/blog/1883488 Maven强大的一个重要的原因是它有一个十分完善的生命周期模型(lifecycle),它有三套相互独立的生命周期,请注意 ...

  8. iOS NSURLConnection和异步网络请求

    在日常应用中,我们往往使用AFNetworking等第三方库来实现网络请求部分.这篇文章会简要地介绍一下如何使用NSURLConnection来进行异步的网络请求. 我们先看一个小demo - (vo ...

  9. mysql cluster 运行的必备条件

    1.由于同步复制一共需要4次消息传递,故mysql  cluster的数据更新速度比单机mysql要慢.所以mysql cluster要求运行在千兆以上的局域网内,节点可以采用双网卡,节点组之间采用直 ...

  10. 修改Tomcat服务器的默认端口号

    tomcat服务器的默认端口号是8080,我们也可以修改为其他端口号,并且在没有启动Apache,IIS等占用80端口的web服务时,我们也可以设置为80端口,这样在生产中域名之后就可以不带端口号了, ...