Android中即时通讯协议选择

Android开源移动端即时通讯比较:SipDroid、IMSDroid、CSipsimple、Linphone和WebRTC 通过上述比较和代码示例,我们可以看到这五个开源解决方案在Android移动端IM领域各具特点。SipDroid和CSipsimple主要基于SIP协议,IMSDroid基于IMS协议,而Linphone和WebRTC提供了更广泛的功能和灵活性。开发人员可以根据自己的需求选择合适的解决方案据自己的需求选择合适的解决方案,并根据示例代码进行开发和定制化。本文将比较并介绍SipDroid、IMSDroid、CSipsimple、Linphone和WebRTC这五个开源解决方案,它们各自的特点及其对应的源代码。 阅读详情

1、Xmpp,Mqtt,Socket对比

Android中的即时通讯,就是客户端要与服务器建立长时间的连接,正常情况下Android中请求服务器数据后,连接一般断开。但即时通讯类的对消息的实时性要求比较高。需要客户端与服务器建立长时间的连接,这样,才能保证消息的时实性。

这里写图片描述

2、XMPP协议

1、XMPP基于xml,XMPP用TCP传递的是xml流。它具有xml的灵活性和扩展性。可以实现服务类实时通讯。

XMPP的核心XML流传输协议的定义使得XMPP能够在一个比以往网络通信协议更规范的平台上。借助于XML易于解析和阅读的特性。

XMPP核心协议通信的基本模式就是先建立一个stream,然后协商一堆安全之类的东西,中间通信过程就是客户端发送XML Stanza,一个接一个的。服务器根据客户端发送的信息以及程序的逻辑,发送XML Stanza给客户端。但是这个过程并不是一问一答的,任何时候都有可能从一方发信给另外一方。通信的最后阶段是关闭流,关闭TCP/IP连接。

3、MQTT协议

这里写图片描述
MQTT(Message Queuing Telemetry Transport)是IBM开发的一个即时通讯的协议。
MQTT的特点:
1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合;
2、对负载内容屏蔽的消息传输;
3、使用 TCP/IP 提供网络连接;
4、有三种消息发布服务质量:
“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。
“至少一次”,确保消息到达,但消息重复可能会发生。
“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;

MQTT非常适合作为Android手机客户端与服务器推送消息。其中Sohu,Cmstop手机客户端中均有使用到MQTT作为消息推送消息。据Cmstop主要负责消息推送的高级研发工程师李文凯称,随着移动互联网的发展,MQTT由于开放源代码,耗电量小等特点,将会在移动消息推送领域会有更多的贡献,在物联网领域,传感器与服务器的通信,信息的收集,MQTT都可以作为考虑的方案之一。
使用方法
导入IBM提供的mqtt.jar包
然后在代码中配置如下。
在其他博客中有详细的配置参见
http://blog.youkuaiyun.com/i_lovefish/article/details/8586435

4、Xmpp实现代码

xmpp断线重连
http://blog.youkuaiyun.com/androidxiaogang/article/details/51603933
1、配置

public class XmppContacts {

    public static final String XMPP_HOST = "x.x.x.x"; // XMPP服务器ip地址
    public static final int XMPP_PORT = 8088; // XMPP服务器客户端访问端口号
    public static final int XMPP_PORT_MANAGER = 8099; // XMPP服务器后台访问端口号
    public static final String XMPP_NAME = "localhost.localhost"; // XMPP服务器名称
    private static final String XMPP_CLIENT_RESOURCE = "Smack"; // XMPP客户端名称

2、创建连接

    private static boolean openConnection() {
            // 建立连接配置信息对象
            ConnectionConfiguration connConfig = new ConnectionConfiguration(
                    XmppContacts.XMPP_HOST, XmppContacts.XMPP_PORT,
                    XmppContacts.XMPP_NAME);
            // 允许重复连接
            connConfig.setReconnectionAllowed(true);
            // 其他配置
            connConfig.setSendPresence(false);
            connConfig
                    .setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
            connConfig.setDebuggerEnabled(XmppContacts.XMPP_DEBUG_MODEL); // 调试模式
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                connConfig.setTruststoreType("AndroidCAStore");
                connConfig.setTruststorePassword(null);
                connConfig.setTruststorePath(null);
            } else {
                connConfig.setTruststoreType("BKS");
                String path = System.getProperty("javax.net.ssl.trustStore");
                if (path == null)
                    path = System.getProperty("java.home") + File.separator + "etc"
                            + File.separator + "security" + File.separator
                            + "cacerts.bks";
                connConfig.setTruststorePath(path);
            }

            // 创建连接对象
            conn = new XMPPConnection(connConfig);
            try {
                conn.connect();
                // 配置各种Provider
                configureConnection(ProviderManager.getInstance());
                return true;
            } catch (XMPPException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return false;
        }

关闭连接

    /**
         * 关闭XMPP连接
         */
        public static void closeConnection() {
            if (conn.isConnected()) {
                System.out.println("---------xmpp将要关闭");
                conn.disconnect();
            }
            conn = null;
        }

3、Mqtt实现代码

在Android中开启一个Service

public class PushService extends Service  
{  
    // this is the log tag  
    public static final String      TAG = "PushService";  

    // the IP address, where your MQTT broker is running.  
    private static final String     MQTT_HOST = "172.16.26.41";//需要改成服务器IP  
    // the port at which the broker is running.   
    private static int              MQTT_BROKER_PORT_NUM      = 1883;//需要改成服务器port  
    // Let's not use the MQTT persistence.  
    private static MqttPersistence  MQTT_PERSISTENCE          = null;  
    // We don't need to remember any state between the connections, so we use a clean start.   
    private static boolean          MQTT_CLEAN_START          = true;  
    // Let's set the internal keep alive for MQTT to 15 mins. I haven't tested this value much. It could probably be increased.  
    private static short            MQTT_KEEP_ALIVE           = 60 * 15;  
    // Set quality of services to 0 (at most once delivery), since we don't want push notifications   
    // arrive more than once. However, this means that some messages might get lost (delivery is not guaranteed)  
    private static int[]            MQTT_QUALITIES_OF_SERVICE = { 0 } ;  
    private static int              MQTT_QUALITY_OF_SERVICE   = 0;  
    // The broker should not retain any messages.  
    private static boolean          MQTT_RETAINED_PUBLISH     = false;  

    // MQTT client ID, which is given the broker. In this example, I also use this for the topic header.   
    // You can use this to run push notifications for multiple apps with one MQTT broker.   
    public static String            MQTT_CLIENT_ID = "ata";//需要改成自己需要的名称  

    // These are the actions for the service (name are descriptive enough)  
    private static final String     ACTION_START = MQTT_CLIENT_ID + ".START";  
    private static final String     ACTION_STOP = MQTT_CLIENT_ID + ".STOP";  
    private static final String     ACTION_KEEPALIVE = MQTT_CLIENT_ID + ".KEEP_ALIVE";  
    private static final String     ACTION_RECONNECT = MQTT_CLIENT_ID + ".RECONNECT";  

    private ConnectivityManager     mConnMan;  
    private NotificationManager     mNotifMan;    
    private boolean                 mStarted;  
    private static final long       KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;  

    // Retry intervals, when the connection is lost.  
    private static final long       INITIAL_RETRY_INTERVAL = 1000 * 10;  
    private static final long       MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;  

    // Preferences instance   
    private SharedPreferences       mPrefs;  
    // We store in the preferences, whether or not the service has been started  
    //判断Service是否已经启动,不要重复启动!  
    public static final String      PREF_STARTED = "isStarted";  
    // We also store the deviceID (target)  
    //需要提供手机设备号,该设备号应该事先保存在SharedPreferences中  
    public static final String      PREF_DEVICE_ID = "deviceID";  
    // We store the last retry interval  
    public static final String      PREF_RETRY = "retryInterval";  

    // Notification title  
    public static String            NOTIF_TITLE = "ata"; //需要改成自己需要的title     
    // Notification id  
    private static final int        NOTIF_CONNECTED = 0;      

    // This is the instance of an MQTT connection.  
    private MQTTConnection          mConnection;  
    private long                    mStartTime;  


    // Static method to start the service  
    //在需要的地方直接调用该方法就启动监听了  
    public static void actionStart(Context ctx) {  
        Intent i = new Intent(ctx, PushService.class);  
        i.setAction(ACTION_START);  
        ctx.startService(i);  
    }  

    // Static method to stop the service  
    public static void actionStop(Context ctx) {  
        Intent i = new Intent(ctx, PushService.class);  
        i.setAction(ACTION_STOP);  
        ctx.startService(i);  
    }  

    // Static method to send a keep alive message  
    public static void actionPing(Context ctx) {  
        Intent i = new Intent(ctx, PushService.class);  
        i.setAction(ACTION_KEEPALIVE);  
        ctx.startService(i);  
    }  

    @Override  
    public void onCreate() {  
        super.onCreate();  

        log("Creating service");  
        mStartTime = System.currentTimeMillis();  

        /*try { 
            //mLog = new ConnectionLog(); 
            //Log.i(TAG, "Opened log at " + mLog.getPath()); 
        } catch (IOException e) { 
            Log.e(TAG, "Failed to open log", e); 
        }*/  

        // Get instances of preferences, connectivity manager and notification manager  
        mPrefs = getSharedPreferences(TAG, MODE_PRIVATE);  
        mConnMan = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);  
        mNotifMan = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);  

        /* If our process was reaped by the system for any reason we need 
         * to restore our state with merely a call to onCreate.  We record 
         * the last "started" value and restore it here if necessary. */  
        handleCrashedService();  
    }  

    // This method does any necessary clean-up need in case the server has been destroyed by the system  
    // and then restarted  
    private void handleCrashedService() {  
        if (wasStarted() == true) {  
            log("Handling crashed service...");  
             // stop the keep alives  
            stopKeepAlives();   

            // Do a clean start  
            start();  
        }  
    }  

    @Override  
    public void onDestroy() {  
        log("Service destroyed (started=" + mStarted + ")");  

        // Stop the services, if it has been started  
        if (mStarted == true) {  
            stop();  
        }  

    /*  try { 
            if (mLog != null) 
                mLog.close(); 
        } catch (IOException e) {}      */  
    }  

    @Override  
    public void onStart(Intent intent, int startId) {  
        super.onStart(intent, startId);  
        log("Service started with intent=" + intent);  

        // Do an appropriate action based on the intent.  
        if (intent.getAction().equals(ACTION_STOP) == true) {  
            stop();  
            stopSelf();  
        } else if (intent.getAction().equals(ACTION_START) == true) {  
            start();  
        } else if (intent.getAction().equals(ACTION_KEEPALIVE) == true) {  
            keepAlive();  
        } else if (intent.getAction().equals(ACTION_RECONNECT) == true) {  
            if (isNetworkAvailable()) {  
                reconnectIfNecessary();  
            }  
        }  
    }  

    @Override  
    public IBinder onBind(Intent intent) {  
        return null;  
    }  

    // log helper function  
    private void log(String message) {  
        log(message, null);  
    }  
    private void log(String message, Throwable e) {  
        if (e != null) {  
            Log.e(TAG, message, e);  

        } else {  
            Log.i(TAG, message);              
        }  

        /*if (mLog != null) 
        { 
            try { 
                mLog.println(message); 
            } catch (IOException ex) {} 
        }       */  
    }  

    // Reads whether or not the service has been started from the preferences  
    private boolean wasStarted() {  
        return mPrefs.getBoolean(PREF_STARTED, false);  
    }  

    // Sets whether or not the services has been started in the preferences.  
    private void setStarted(boolean started) {  
        mPrefs.edit().putBoolean(PREF_STARTED, started).commit();         
        mStarted = started;  
    }  

    private synchronized void start() {  
        log("Starting service...");  

        // Do nothing, if the service is already running.  
        if (mStarted == true) {  
            Log.w(TAG, "Attempt to start connection that is already active");  
            return;  
        }  

        // Establish an MQTT connection  
        connect();  

        // Register a connectivity listener  
        registerReceiver(mConnectivityChanged, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));        
    }  

    private synchronized void stop() {  
        // Do nothing, if the service is not running.  
        if (mStarted == false) {  
            Log.w(TAG, "Attempt to stop connection not active.");  
            return;  
        }  

        // Save stopped state in the preferences  
        setStarted(false);  

        // Remove the connectivity receiver  
        unregisterReceiver(mConnectivityChanged);  
        // Any existing reconnect timers should be removed, since we explicitly stopping the service.  
        cancelReconnect();  

        // Destroy the MQTT connection if there is one  
        if (mConnection != null) {  
            mConnection.disconnect();  
            mConnection = null;  
        }  
    }  

    //   
    private synchronized void connect() {         
        log("Connecting...");  
        // fetch the device ID from the preferences.  
        String deviceID = mPrefs.getString(PREF_DEVICE_ID, null);  
        // Create a new connection only if the device id is not NULL  
        if (deviceID == null) {  
            log("Device ID not found.");  
        } else {  
            try {  
                mConnection = new MQTTConnection(MQTT_HOST, deviceID);  
            } catch (MqttException e) {  
                // Schedule a reconnect, if we failed to connect  
                log("MqttException: " + (e.getMessage() != null ? e.getMessage() : "NULL"));  
                if (isNetworkAvailable()) {  
                    scheduleReconnect(mStartTime);  
                }  
            }  
            setStarted(true);  
        }  
    }  

    private synchronized void keepAlive() {  
        try {  
            // Send a keep alive, if there is a connection.  
            if (mStarted == true && mConnection != null) {  
                mConnection.sendKeepAlive();  
            }  
        } catch (MqttException e) {  
            log("MqttException: " + (e.getMessage() != null? e.getMessage(): "NULL"), e);  

            mConnection.disconnect();  
            mConnection = null;  
            cancelReconnect();  
        }  
    }  

    // Schedule application level keep-alives using the AlarmManager  
    private void startKeepAlives() {  
        Intent i = new Intent();  
        i.setClass(this, PushService.class);  
        i.setAction(ACTION_KEEPALIVE);  
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);  
        AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);  
        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,  
          System.currentTimeMillis() + KEEP_ALIVE_INTERVAL,  
          KEEP_ALIVE_INTERVAL, pi);  
    }  

    // Remove all scheduled keep alives  
    private void stopKeepAlives() {  
        Intent i = new Intent();  
        i.setClass(this, PushService.class);  
        i.setAction(ACTION_KEEPALIVE);  
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);  
        AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);  
        alarmMgr.cancel(pi);  
    }  

    // We schedule a reconnect based on the starttime of the service  
    public void scheduleReconnect(long startTime) {  
        // the last keep-alive interval  
        long interval = mPrefs.getLong(PREF_RETRY, INITIAL_RETRY_INTERVAL);  

        // Calculate the elapsed time since the start  
        long now = System.currentTimeMillis();  
        long elapsed = now - startTime;  


        // Set an appropriate interval based on the elapsed time since start   
        if (elapsed < interval) {  
            interval = Math.min(interval * 4, MAXIMUM_RETRY_INTERVAL);  
        } else {  
            interval = INITIAL_RETRY_INTERVAL;  
        }  

        log("Rescheduling connection in " + interval + "ms.");  

        // Save the new internval  
        mPrefs.edit().putLong(PREF_RETRY, interval).commit();  

        // Schedule a reconnect using the alarm manager.  
        Intent i = new Intent();  
        i.setClass(this, PushService.class);  
        i.setAction(ACTION_RECONNECT);  
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);  
        AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);  
        alarmMgr.set(AlarmManager.RTC_WAKEUP, now + interval, pi);  
    }  

    // Remove the scheduled reconnect  
    public void cancelReconnect() {  
        Intent i = new Intent();  
        i.setClass(this, PushService.class);  
        i.setAction(ACTION_RECONNECT);  
        PendingIntent pi = PendingIntent.getService(this, 0, i, 0);  
        AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);  
        alarmMgr.cancel(pi);  
    }  

    private synchronized void reconnectIfNecessary() {        
        if (mStarted == true && mConnection == null) {  
            log("Reconnecting...");  
            connect();  
        }  
    }  

    // This receiver listeners for network changes and updates the MQTT connection  
    // accordingly  
    private BroadcastReceiver mConnectivityChanged = new BroadcastReceiver() {  
        @Override  
        public void onReceive(Context context, Intent intent) {  
            // Get network info  
            NetworkInfo info = (NetworkInfo)intent.getParcelableExtra (ConnectivityManager.EXTRA_NETWORK_INFO);  

            // Is there connectivity?  
            boolean hasConnectivity = (info != null && info.isConnected()) ? true : false;  

            log("Connectivity changed: connected=" + hasConnectivity);  

            if (hasConnectivity) {  
                reconnectIfNecessary();  
            } else if (mConnection != null) {  
                // if there no connectivity, make sure MQTT connection is destroyed  
                mConnection.disconnect();  
                cancelReconnect();  
                mConnection = null;  
            }  
        }  
    };  

    // Display the topbar notification  
    private void showNotification(String content) {  
        Notification n = new Notification();  

        n.flags |= Notification.FLAG_SHOW_LIGHTS;  
        n.flags |= Notification.FLAG_AUTO_CANCEL;  

        n.defaults = Notification.DEFAULT_ALL;  

        n.icon = R.drawable.ic_dialog_info;  
        n.when = System.currentTimeMillis();  

        Log.i("PushService", "json==="+content);  
        String alert=null;  
        String id=null;  
        try {  
            JSONObject json = new JSONObject(content);  
            alert = json.optString("alert");  
            id = json.optString("id");  
        } catch (JSONException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  

        Intent intent = new Intent(this,NewMesageInfoActivity.class);         
        intent.putExtra("url", "http://testing.portal.ataudc.com/message/"+id);  
        intent.putExtra("id", id);  
        PendingIntent pi = PendingIntent.getActivity(this, 0,intent, PendingIntent.FLAG_ONE_SHOT);  
        // Change the name of the notification here  
        n.setLatestEventInfo(this, NOTIF_TITLE, alert, pi);  

        mNotifMan.notify(NOTIF_CONNECTED, n);  
    }  

    // Check if we are online  
    private boolean isNetworkAvailable() {  
        NetworkInfo info = mConnMan.getActiveNetworkInfo();  
        if (info == null) {  
            return false;  
        }  
        return info.isConnected();  
    }  

    // This inner class is a wrapper on top of MQTT client.  
    private class MQTTConnection implements MqttSimpleCallback {  
        IMqttClient mqttClient = null;  

        // Creates a new connection given the broker address and initial topic  
        public MQTTConnection(String brokerHostName, String initTopic) throws MqttException {  
            // Create connection spec  
            String mqttConnSpec = "tcp://" + brokerHostName + "@" + MQTT_BROKER_PORT_NUM;  
                // Create the client and connect  
                mqttClient = MqttClient.createMqttClient(mqttConnSpec, MQTT_PERSISTENCE);  
                String clientID = MQTT_CLIENT_ID + "/" + mPrefs.getString(PREF_DEVICE_ID, "");  
                mqttClient.connect(clientID, MQTT_CLEAN_START, MQTT_KEEP_ALIVE);  

                // register this client app has being able to receive messages  
                mqttClient.registerSimpleHandler(this);  

                // Subscribe to an initial topic, which is combination of client ID and device ID.  
                initTopic = MQTT_CLIENT_ID + "/" + initTopic;  
                subscribeToTopic(initTopic);  

                log("Connection established to " + brokerHostName + " on topic " + initTopic);  

                // Save start time  
                mStartTime = System.currentTimeMillis();  
                // Star the keep-alives  
                startKeepAlives();                        
        }  

        // Disconnect  
        public void disconnect() {  
            try {             
                stopKeepAlives();  
                mqttClient.disconnect();  
            } catch (MqttPersistenceException e) {  
                log("MqttException" + (e.getMessage() != null? e.getMessage():" NULL"), e);  
            }  
        }  

        private void subscribeToTopic(String topicName) throws MqttException {  

            if ((mqttClient == null) || (mqttClient.isConnected() == false)) {  
                // quick sanity check - don't try and subscribe if we don't have  
                //  a connection  
                log("Connection error" + "No connection");    
            } else {                                      
                String[] topics = { topicName };  
                mqttClient.subscribe(topics, MQTT_QUALITIES_OF_SERVICE);  
            }  
        }     
        private void publishToTopic(String topicName, String message) throws MqttException {          
            if ((mqttClient == null) || (mqttClient.isConnected() == false)) {  
                // quick sanity check - don't try and publish if we don't have  
                //  a connection                  
                log("No connection to public to");        
            } else {  
                mqttClient.publish(topicName,   
                                   message.getBytes(),  
                                   MQTT_QUALITY_OF_SERVICE,   
                                   MQTT_RETAINED_PUBLISH);  
            }  
        }         

        /* 
         * Called if the application loses it's connection to the message broker. 
         */  
        public void connectionLost() throws Exception {  
            log("Loss of connection" + "connection downed");  
            stopKeepAlives();  
            // null itself  
            mConnection = null;  
            if (isNetworkAvailable() == true) {  
                reconnectIfNecessary();   
            }  
        }         

        /* 
         * Called when we receive a message from the message broker.  
         * 在这里处理服务器推送过来的数据 
         */  
        public void publishArrived(String topicName, byte[] payload, int qos, boolean retained) {  
            // Show a notification  
            String s = new String(payload);  
            showNotification(s);      
        }     

        public void sendKeepAlive() throws MqttException {  
            log("Sending keep alive");  
            // publish to a keep-alive topic  
            publishToTopic(MQTT_CLIENT_ID + "/keepalive", mPrefs.getString(PREF_DEVICE_ID, ""));  
        }         
    }  
}  

从上面对比,在android端或者移动设备,mqtt在耗电,耗网上都比较适合,与服务器确认请求,只需要发送几个字节。

Android即时通讯应用开发:基于XMPP协议项目实战 本文还有配套的精品资源,点击获取 简介:本项目涉及在Android平台上利用XMPP即时通讯协议构建聊天应用。XMPP是一种开放标准,支持多种实时通讯场景。我们将深入探索如何使用Smack库来实现用户连接、消息发送接收、群组管理等功能,并讨论如何设计UI和处理导航,最终构建一个具备聊天、群聊及用户头像展示等功能的应用。 1. XMPP协议基础及应用 1.1 ... 阅读详情

相关推荐

Android即时通信应用项目:XMPP协议实战

即时通信技术已经成为现代沟通不可或缺的一部分,它的出现极大地改变了人们的生活和工作方式。通过网络实时交换文本消息是即时通信技术的基本功能,但它所涵盖的技术范畴远远不止于此。本章将带领读者了解即时通信技术的发展历程,技术架构,以及在市场中的应用情况,为深入探讨即时通信技术的各个方面打下坚实基础。XML流是XMPP协议中信息交换的基础。它定义了消息、存在状态、订阅请求等不同类型的数据包(Packet)如何被封装和传输。消息类型和状态信息都用XML格式进行编码,并通过 TCP 连接传输。

weixin_29496633的博客 1279

Android即时通讯(一)

资料来自网络: 一、即时通讯 什么是即时通讯? 即时通讯,又称实时通讯 即时通信(Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流 即时通讯在开发中使用的场景 开发一个类型于微信,QQ,易信的聊天软件 在电商APP集成买家与卖家的实时沟通等 当前时下,实现即时通讯的方案 1.XMPP 2.环...

一抹离愁 6731

构建Android即时通讯系统:服务端与客户端实战指南

选择合适的编程语言和框架对于构建高性能、易于维护的服务端应用至关重要。当前,几种主流的编程语言和框架包括:Java:拥有庞大的生态和成熟的框架,例如Spring Boot,对于构建微服务架构的支持很好。Node.js:基于Chrome V8引擎的JavaScript运行时,适用于I/O密集型的应用,具有非阻塞、事件驱动的特性。Go语言:以其并发性能强和编译速度快著称,非常适合于网络服务端的开发。在选择时,需要考虑以下因素:社区支持。

weixin_42499004的博客 917

Android即时通讯系列文章(2)网络通信协议选型:应以什么样的标准去选择适合你应用的网络通信协议?

「椎锋陷陈」微信技术号现已开通,为了获得第一手的技术文章推送,欢迎搜索关注! 前言 在前一篇文章《多进程:为什么要把消息服务拆分到一个独立的进程?》中我们出于保证连接的稳定性的目的,将应用拆分成了「主进程」和「通讯进程」,并为二者定义了相互通信的接口。即便如此,我们也只是实现了客户端一侧的进程间通信,而要实现与完整聊天系统中另一端的角色——服务端的通信,则需依靠「网络通信协议」来协助完成,在此我们选用的是WebSocket协议。 什么是WebSocket? WebSocket一词,从词面上可以拆解为 Web

椎锋陷陈 924

Openfire与XMPP协议在Android即时通讯中的应用解析

Openfire是一个开源的即时消息通信服务器,它基于XMPP(可扩展消息和出席协议)标准,广泛应用于企业级的即时通讯解决方案。本章节将为读者提供Openfire的基本概念,它的安装和配置步骤,以及如何实现一个基本的即时通讯服务器环境。Openfire是一个用Java编写的轻量级服务器,它允许用户创建自己的即时消息服务,实现消息的即时传递、在线状态呈现以及群组交流功能。它提供了良好的用户管理界面和多种插件支持,可以很好地集成到企业现有的信息系统中。

weixin_42591908的博客 346

【obj To 3DTiles 进阶实战】 从零配置地理坐标系与扩展属性元数据

本文详细解析了如何将OBJ模型转换为3DTiles格式,重点介绍了地理坐标系配置与属性元数据扩展的实战技巧。通过obj23dtiles工具,开发者可以精准定位模型经纬高坐标,并添加结构化属性表,实现城市规划模型在数字孪生平台的高效应用。

weixin_27215337的博客 367

android之IM即时通信原理

服务器通过FCM服务器将通知下发到用户的设备,系统会唤醒你的App(或显示通知栏),App可以趁机重新建立长连接,拉取最新消息。A的App:消息输入后,生成一个本地唯一ID,存入本地数据库(状态为“发送中”),通过已建立的长连接(TCP/WebSocket)将消息包(包含消息ID、接收者B、内容等)发送给IM服务器。已读回执:当B点开聊天窗口阅读消息后,B的App会向服务器发送一个“已读回执”(包含已读的消息ID),服务器再转发给A,A更新本地UI。离线消息:用户离线时,服务器会存储发往他的消息。

G3113542273的博客 472

pytorch中dataloader的num_workers参数

结论速递 在Windows系统中,num_workers参数建议设为0,在Linux系统则不需担心。 1 问题描述 在之前的任务超大图上的节点表征学习中,使用PyG库用于数据加载的DataLoader,ClusterLoader等类时,会涉及到参数num_workers。在不同系统环境试验该参数的设定值时,会出现不同的结果 colab(Linux),设为12 有warning message,提示num_workers参数设置不合理,不影响继续运行 /usr/local/lib/python3.7/di

qq_40990057的博客 1万+

教你轻松开发一个Andriod版即时通讯

考虑到作为一个主打社交的产品,消息数据量会非常大,同时为了节约流量,所以采用protobuf是一个不错的选择。1)TCP:缺点就是慢,效率低,占用系统资源高,易被攻击,TCP在传递数据之前要先建立连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞机制等都会消耗大量时间,而且要在每台设备上维护所有的传输连接。2)UDP:优点体现在快,比TCP稍安全,UDP没有TCP拥有的各种机制,是一个无状态的传输协议,所以传递数据非常快,没有TCP的这些机制,被攻击利用的机制就少一些,但是也无法避免被攻击。

蔚可云的博客 2154

uniapp原生安卓插件开发之路

声明: 我的功能需求:全局悬浮框,也就是在其他应用上依旧能悬浮。查遍uni文档,无法实现,甚至native.js也无法实现,无奈只能走上原生插件开发这条不归路了。(吐槽:天天写前端js,突然写了下android简直要炸,public static String啥的,var不香嘛,不过别人严谨肯定还是有别人道理的,加油吧,争取能入个门!) 本人不懂安卓开发,完全安卓小白,所以安卓方面可能表达的不是很好,安卓代码可能写的不优美,但我功能最终还是实现了。但是为了需求,能力总能被“逼”出来。有描述错误的还望指正

Jone's Area 1万+

YOLOv8中的可变形卷积改进 | 从DCNv1到DCNv3的多位置替换可变形卷积保姆级实操

可变形卷积(Deformable Convolution)最早由Dai等人在2017年提出,其核心思想是在标准卷积操作的基础上,引入可学习的偏移量(offsets),使卷积核能够自适应调整其采样位置,从而增强模型对目标变形的感知能力。return x本文通过深入探讨可变形卷积在YOLOv8中的应用,详细介绍了DCNv1、DCNv2和DCNv3的原理和实现,并通过实验验证了其在目标检测任务中的有效性。未来,我们将继续探索更多优化策略和技术,提升YOLOv8模型的性能,以应对更复杂的目标检测任务。

一键难忘的博客 4051

Android 平台下的即时通讯

该文章转载于http://skywen.iteye.com/blog/1811310

little_rui的专栏 1355

最适合入门的100个深度学习项目

本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

优快云 精品推荐 12万+

open-im-android-demo:构建即时通讯应用的强大基石

open-im-android-demo:构建即时通讯应用的强大基石 在当今信息化时代,即时通讯应用已成为人们日常生活不可或缺的一部分。对于开发者而言,如何构建一个安全、高效且用户友好的即时通讯应用显得尤为重要。open-im-android-demo 作为一款开源的即时通讯 SDK,为广大开发者提供了一个强大的工具。 项目介绍 open-im-android-demo 是基于 OpenIM SD...

gitblog_00568的博客 926

基于 Langchain 开发一个完整的支持多轮数据分析(直连 mysql 数据,多表综合分析 SQL 取数,数据分析,报表生成)ChatBI 系统(前后端完整实现源代码)

ChatBI系统开发摘要 本文介绍了基于Langchain的多轮数据分析ChatBI系统开发方案。该系统支持MySQL数据库连接,提供多表分析、SQL查询、数据分析和报表生成功能。系统采用前后端分离架构:前端使用React+Ant Design+ECharts实现交互界面;后端基于FastAPI搭建服务,集成Langchain处理自然语言到SQL的转换;核心技术栈还包括SQLAlchemy、Pandas和Matplotlib。 系统核心模块包括: 数据库连接层:使用SQLAlchemy管理MySQL连接 L

AI天才研究院 816

AUTOSAR-SOMEIP配置总结

导入arxml之后someip信号一般以“pduSomeIp”开头或者“SomeIp”开头。以某个pdu为例,设置项“Pdu Default Partition Ref”主要是根据模块设计,配置相应的Ecuc核分区。在导入arxml之后someip信号中有三个特殊的信号,形如“SdInstance”开头的信号,设置项“Pdu Default Partition Ref”主要是根据模块设计,配置相应的Ecuc核分区。“EcuC”模块主要关注“EcucPduCollection”中的“Pdus”下面的配置。

xiandang8023的博客 4654

Android即时通讯系列文章(0)起源:对接触工作以来所涉及过的即时通讯技术的全面复盘

「椎锋陷陈」微信技术号现已开通,为了获得第一手的技术文章推送,欢迎搜索关注! 为什么想要写这个系列的文章? 2018年年末,由于所在公司的战略方向转向东南亚一隅,意欲打造一款面向东南亚市场的即时通讯应用,并且高层在综合考量之后决定采用自研技术,于是机缘巧合之下我被安排到IM项目组,从而再次接触到了即时通讯技术。 为什么说是再次呢?因为我之前参与开发的两个商业项目同样运用到了即时通讯技术,一个是用到 XMPP+Openfire+Smack,另外一个是用到MQTT,只是当时由于工作经验的关系都只停留在环境的搭建

椎锋陷陈 202

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

MoorePlus的博客 4221

Android实现基于TCP和UDP协议的即时通讯,含android端和服务器端

附带宣传下参与的网站: 最爱明星网:http://zuiaimingxing.com/ 给自己的爱豆打call 这几天学习了下在android中实现即时通讯的方法,一开始,自然是从基本的网络协议中开始尝试了,这样能够最大化的私人订制自己的应用,还能学习到更多的知识,好处多多,接下来就简单介绍下两种协议的不同点吧 TCP协议:提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠...

0-0Xuan的专栏 3523

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

安卓平台下的即时通讯

基于Android 平台简易即时通讯的研究与设计 摘要:论文简单介绍Android 平台的特性,主要阐述了基于Android 平台简易即时通讯(IM)的作用和功能以及实现方法,复杂的通讯如引入视频音频等可以考虑AnyChat SDK。关键词:Android 平台;即时通讯 1 Android 平台简介Android 是Google 公司于2007年11月5日推出的手机操作系统,经过2年多的发展...

44

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

即时通讯文章推荐分享-不定时更新

即时通讯

我是小彬彬 395

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

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

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

qq_30548105的博客 831

Android--Android平台即时通信系统

Android平台即时通信系统

Navan 702

Android 即时通讯开发小结(一)

《Android 即时通讯开发小结》基于IMAndriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对IM开发做一个全面的总结。 相关推荐阅读:、 Android 即时通讯开发小结(二) 移动IM开发指南1:如何进行技术选型 移动IM开发指南2:心跳指令详解 移动IM开发指南3:如何优化登录模块 客户端架构 作为一个IM 软件,最重要的一个特性就是保证消...

weixin_33711641的博客 93

即时通讯 MQTT

即时通讯 MQTT 错误汇总 mqtt连接断开,(32109) - java.io.EOFException错误 原因:客户端唯一标识重复导致的 参考 MQTT协议笔记之连接和心跳 Mqtt精髓系列之心跳机制 MQTT协议(二)连接和心跳 MQTT协议之连接和心跳介绍 MQTT协议及应用场景 ...

初心一点的专栏 1574
上一篇: Android RecyclerView
下一篇: Listview Checkbox错乱问题
android_xiaogang
博客等级 码龄12年 89粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值