android 初入坑xmpp即时通讯(一)

之前做了一个神秘的政府项目,此处保密。里面用的东西奇多,又是专网。抛弃了各种第三方。原本刚来,不知道是用专网(这里近似看作局域网吧),我很兴奋的用极光,环信还有网易云之类的,还互相比较,最后慢慢写,写了近一个星期,就只差群聊就做完了。。。然后被通知是专网。。全部删掉了。想哭。。。


这里还是建议考虑项目需求,再选择使用那种方案,用第三方的这些集成好的sdk也挺好的。


XMPP(Extensible Messageing and Presence Protocol:可扩展消息与存在协议)是目前主流的四种IM(IM:instant messaging,即时消息)协议之一,其他三种分别为:即时信息和空间协议(IMPP)、空间和即时信息协议(PRIM)、针对即时通讯和空间平衡扩充的进程开始协议SIP(SIMPLE)。


这些是相对成熟稳定的xmpp客户端软件:

spark

Psi

JWChat


xmpp服务器端:

openfire

tigase

iChatServer (通常用于IOS)

jabberd2


xmpp Library:

Smack (java)

Asmack (java)

gloox (C++)


这里需要注意的是,据说openfire最多就30w用户(还是修改源码优化的),tigase的商业版本支持到1400w。

现在smack(4.1以上版本)也可以直接运行Android平台上了,所以可以看到asmack也没有什么更新了。

openfire 下载地址:http://www.igniterealtime.org/downloads/index.jsp



对于安装,配置什么的,我就不多说了。

Android 端需要导入一个jar包,因为java是使用smack进行开发,而Asmack是针对android 改造的smack,所以我们采用Asmack即可。

网上有很多的jar包版本,我这里使用的是



这里也有简单的asmack对应的API中文文档供参考:http://download.csdn.net/download/arinasiyyj/7816239


那么接下来,咱们就先从登陆入手。

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp">
        <EditText
            android:id="@+id/et_username"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:hint="用户名"
            android:paddingLeft="10dp"
            android:gravity="center_vertical"
            android:paddingRight="10dp"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp">
        <EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:hint="密码"
            android:paddingLeft="10dp"
            android:gravity="center_vertical"
            android:paddingRight="10dp"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp">
        <EditText
            android:id="@+id/et_server"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:hint="服务器"
            android:paddingLeft="10dp"
            android:gravity="center_vertical"
            android:paddingRight="10dp"/>
    </android.support.design.widget.TextInputLayout>
        <Button
            android:id="@+id/bt_login"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginRight="10dp"
            android:text="登陆"/>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <CheckBox
            android:id="@+id/ck_savepwd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="记住密码"
            />
        <CheckBox
            android:id="@+id/ck_autologin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:text="自动登录"
            />
    </RelativeLayout>
    <Button
        android:id="@+id/bt_register"
        android:layout_width="90dp"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="right"
        android:text="注册"/>

</LinearLayout>

Login:

    @OnClick({R.id.bt_login, R.id.bt_register})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_login:
                // 切记登陆连接服务器操作不能放在主线程操作
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if (login()){
                            startActivity(new Intent(LoginActivity.this,MainActivity.class));
                            finish();
                        }else {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(LoginActivity.this,"登陆失败,请检查用户名,密码或者服务器IP是否输入正确!",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                }).start();
                break;
            case R.id.bt_register:
                startActivity(new Intent(LoginActivity.this,RegisterActivity.class));
                break;
        }
    }


    private boolean login(){
        try {
            XMPPConnection connection = XMPPUtil.getXMPPConnection(myLoginData.LoginServer);
            if (connection == null) {
                Log.i("tag","failed");
                throw new Exception("连接服务器失败!");
            }
              connection.login(myLoginData.username, myLoginData.password);  //连接服务器
//            Roster mRoster=connection.getRoster();   //获取花名册
//            RosterGroup group = mRoster.createGroup("facehand");  //创建默认分组
              MySave.setXMPPConnection(this,connection);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }

具体连接服务器操作:

package com.mychat.myxmpp.common;

import android.util.Log;

import com.mychat.myxmpp.XMPPUtilClient;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;


/**
 * Created by 李硕 QQ:752231513 on 2016/7/22.
 */

public class XMPPUtil {
    public static XMPPConnection getXMPPConnection(String server, int port) {
        try {
            //配置configuration
            ConnectionConfiguration configuration = new ConnectionConfiguration(server, port);
            configuration.setReconnectionAllowed(true);   //重连许可
            //设置安全类型
            configuration.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
            configuration.setSendPresence(true);
            //设置不需要SAS验证
            // configuration.setSASLAuthenticationEnabled(false);
            configure(ProviderManager.getInstance());
            SASLAuthentication.supportSASLMechanism("PLAIN", 0);  // SASL 的认证方式
            XMPPConnection connection = new XMPPConnection(configuration, null);
            connection.connect();
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    public static XMPPConnection getXMPPConnection(String server){
        return getXMPPConnection(server,5222);  //openfire 默认端口号 5222  如果冲突会加1,依次类推
    }

    /*
    * 下面这个是我在执行搜索查询用户时总是会报空指针 * smack.providers 的文件不能载入asmack中导致的。所以必须我们自己手动载入一个。 * 所以加入下面代码,在xmppConnection是实例化之前载入即可
    * */
    public static void configure(ProviderManager pm) {

//  Private Data Storage
        pm.addIQProvider("query","jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());

//  Time
        try {
            pm.addIQProvider("query","jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
        } catch (ClassNotFoundException e) {
            Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time");
        }

//  Roster Exchange
        pm.addExtensionProvider("x","jabber:x:roster", new RosterExchangeProvider());

//  Message Events
        pm.addExtensionProvider("x","jabber:x:event", new MessageEventProvider());

//  Chat State
        pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
        pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
        pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
        pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
        pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

//  XHTML
        pm.addExtensionProvider("html","http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());

//  Group Chat Invitations
        pm.addExtensionProvider("x","jabber:x:conference", new GroupChatInvitation.Provider());

//  Service Discovery # Items
        pm.addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());

//  Service Discovery # Info
        pm.addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());

//  Data Forms
        pm.addExtensionProvider("x","jabber:x:data", new DataFormProvider());

//  MUC User
        pm.addExtensionProvider("x","http://jabber.org/protocol/muc#user", new MUCUserProvider());

//  MUC Admin
        pm.addIQProvider("query","http://jabber.org/protocol/muc#admin", new MUCAdminProvider());

//  MUC Owner
        pm.addIQProvider("query","http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());

//  Delayed Delivery
        pm.addExtensionProvider("x","jabber:x:delay", new DelayInformationProvider());

//  Version
        try {
            pm.addIQProvider("query","jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
        } catch (ClassNotFoundException e) {
            //  Not sure what's happening here.
        }

//  VCard
        pm.addIQProvider("vCard","vcard-temp", new VCardProvider());

//  Offline Message Requests
        pm.addIQProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());

//  Offline Message Indicator
        pm.addExtensionProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());

//  Last Activity
        pm.addIQProvider("query","jabber:iq:last", new LastActivity.Provider());

//  User Search
        pm.addIQProvider("query","jabber:iq:search", new UserSearch.Provider());

//  SharedGroupsInfo
        pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());

//  JEP-33: Extended Stanza Addressing
        pm.addExtensionProvider("addresses","http://jabber.org/protocol/address", new MultipleAddressesProvider());

//   FileTransfer
        pm.addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());

        pm.addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());

//  Privacy
        pm.addIQProvider("query","jabber:iq:privacy", new PrivacyProvider());
        pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
        pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.MalformedActionError());
        pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadLocaleError());
        pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadPayloadError());
        pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadSessionIDError());
        pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.SessionExpiredError());

    }

}


 之后自己记得做一些个人信息的缓存,登陆信息的储存就可以完成登陆了,我这个是从登陆入手,记得在服务器端手动注册一个账号就行





实在太忙,有时间继续接着写。。。又被催着写项目去了


本人个人原创,如有雷同,纯属巧合,或者与本人联系,做改动。请转载或者CV组合标明出处,谢谢!


猜你喜欢

转载自blog.csdn.net/qq_30548105/article/details/52606093