1. 程式人生 > >android長連線實現

android長連線實現

本文中我們將講解一下App的長連線實現。一般而言長連線已經是App的標配了,推送功能的實現基礎就是長連線,當然了我們也可以通過輪訓操作實現推送功能,但是輪訓一般及時性比較差,而且網路消耗與電量銷燬比較多,因此一般推送功能都是通過長連線實現的。

那麼如何實現長連線呢?現在一般有這麼幾種實現方式:

  • 使用第三方的長連線服務;

  • 通過NIO等方案實現長連線服務;

  • 通過MINA等第三方框架實現長連線;

幾種長連線服務的具體實現,以及各自的優缺點。

1. 使用第三方的長連線服務

介紹:這是最簡單的方式,我們可以通過接入極光推送,百度推送,友盟等第三方服務實現長連線,通過接入第三方的API我們可以很方便的接入第三方的長連線,推送服務,但是這種方式定製化程度不太好,如果對長連線服務不是要求特別高,對定製化要求不是很高的話基本可以考慮這種方式(目前主流的App都是使用第三方的長連線服務) 
優勢:簡單,方便 
劣勢:定製化程度不高

2. 使用NIO等方案實現長連線服務

介紹:通過NIO的方式實現長連線,這種方式對技術要求程度比較高,基本都是通過java API實現長連線,實現心跳包,實現異常情況的容錯等操作,可以說通過NIO實現長連線對技術要求很高,一般如果沒有成行的技術方案比建議這麼做,就算實現了長連線,後期連線的維護,對電量,流量的損耗等都需要持續的優化。 
優勢:定製化比較高 
劣勢:技術要求高,需要持續的維護

3. 使用MINA等第三方框架實現長連線

介紹:MINA是一個第三方的NIO框架,該框架實現了一整套的長連線機制,包括長連線的建立,心跳包的實現,異常機制的容錯等。使用MINA實現長連線可以定製化的實現一些特有的功能,並且比NIO方案較為簡單,因為其已經封裝了一些長連線的特有機制,比如心跳包,容錯等。 
優勢:可定製,較NIO方法簡單 
劣勢:也需要一定的技術儲備

長連線具體實現

在我們的Android客戶端中長連線的實現機制採用–MINA方式。這裡多說一句,一開始的長連線採用的是NIO方案,但是採用這種方案之後踩了很多坑,包括心跳,容錯等機制都是自己寫的,所以耗費了大量的時間,而且對手機電量的消耗很大,最後決定使用MINA NIO框架重新實現一遍長連線,後來經過實測,長連線的穩定性還有耗電量,流量的消耗等指標方面有了很大的提高。

下面我將簡單的介紹一下通過NIO實現長連線的具體流程:

  • 引入MINA jar包,在App啟動頁面,登入頁面啟動長連線;

  • 建立後臺服務,在服務中建立MINA長連線;

  • 實現心跳包,重寫一些容錯機制;

  • 實現長連線斷了之後的重連機制,並且重連次數有限制不能一直重連;

  • 長連線斷了之後實現輪訓操作,這裡的輪訓服務只有在長連線斷了之後才啟動,在長連線恢復之後關閉;

以下就是在長連線中實現的具體程式碼:

  • 在Application的onCreate方法中檢測App是否登入,若登入的話啟動長連線
/**
 * 在Application的onCreate方法中執行啟動長連線的操作
 **/
@Override
    public void onCreate() {
        ...
        // 登入後開啟長連線
        if (UserConfig.isPassLogined()) {
            L.i("使用者已登入,開啟長連線...");
            startLongConn();
        }
        ...
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 通過鬧鐘服務實現具體的啟動長連線service的操作,即每隔60秒鐘判斷長連線是否啟動,若未啟動則實現啟動操作
    /**
     * 開始執行啟動長連線服務
     */
    public void startLongConn() {
        quitLongConn();
        L.i("長連線服務已開啟");
        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, LongConnService.class);
        intent.setAction(LongConnService.ACTION);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        long triggerAtTime = SystemClock.elapsedRealtime();
        manager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 60 * 1000, pendingIntent);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 下面的程式碼就是長連線服務的具體實現
/**
 * 後臺長連線服務
 **/
public class LongConnService extends Service {
    public static String ACTION = "com.youyou.uuelectric.renter.Service.LongConnService";
    private static MinaLongConnectManager minaLongConnectManager;
    public String tag = "LongConnService";
    private Context context;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = getApplicationContext();
        // 執行啟動長連線的操作
        startLongConnect();
        ObserverManager.addObserver("LongConnService", stopListener);
        return START_STICKY;
    }

    public ObserverListener stopListener = new ObserverListener() {
        @Override
        public void observer(String from, Object obj) {
            closeConnect();
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeConnect();
    }

    /**
     * 開始執行啟動長連線的操作
     */
    private void startLongConnect() {
        if (Config.isNetworkConnected(context)) {
            if (minaLongConnectManager != null && minaLongConnectManager.checkConnectStatus()) {
                L.i("長連線狀態正常...");
                return;
            }
            if (minaLongConnectManager == null) {
                startThreadCreateConnect();
            } else {
                if (minaLongConnectManager.connectIsNull() && minaLongConnectManager.isNeedRestart()) {
                    L.i("session已關閉,需要重新建立一個session");
                    minaLongConnectManager.startConnect();
                } else {
                    L.i("長連線已關閉,需要重開一個執行緒來重新建立長連線");
                    startThreadCreateConnect();
                }
            }
        }

    }

    private final AtomicInteger mCount = new AtomicInteger(1);

    private void startThreadCreateConnect() {
        if (UserConfig.getUserInfo().getB3Key() != null && UserConfig.getUserInfo().getSessionKey() != null) {
            System.gc();

            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 執行具體啟動長連線操作
                    minaLongConnectManager = MinaLongConnectManager.getInstance(context);
                    minaLongConnectManager.crateLongConnect();
                }
            }, "longConnectThread" + mCount.getAndIncrement()).start();
        }
    }


    private void closeConnect() {

        if (minaLongConnectManager != null) {
            minaLongConnectManager.closeConnect();
        }
        minaLongConnectManager = null;

        // 停止長連線服務LongConnService
        stopSelf();
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 而下面的程式碼就是長連線的具體實現操作,具體的程式碼有相關注釋說明
/**
 * 具體實現長連線的管理物件
 **/
public class MinaLongConnectManager {

    private static final String TAG = MinaLongConnectManager.class.getSimpleName();
    /**
     * 伺服器埠號
     */
    public static final int DEFAULT_PORT = 18156;
    /**
     * 連線超時時間,30 seconds
     */
    public static final long SOCKET_CONNECT_TIMEOUT = 30 * 1000L;

    /**
     * 長連線心跳包傳送頻率,60s
     */
    public static final int KEEP_ALIVE_TIME_INTERVAL = 60;
    private static Context context;
    private static MinaLongConnectManager minaLongConnectManager;

    private static NioSocketConnector connector;
    private static ConnectFuture connectFuture;
    public static IoSession session;
    private static ExecutorService executorService = Executors.newSingleThreadExecutor();

    /**
     * 長連線是否正在連線中...
     */
    private static boolean isConnecting = false;

    private MinaLongConnectManager() {
        EventBus.getDefault().register(this);
    }

    public static synchronized MinaLongConnectManager getInstance(Context ctx) {

        if (minaLongConnectManager == null) {
            context = ctx;
            minaLongConnectManager = new MinaLongConnectManager();
        }
        return minaLongConnectManager;
    }

    /**
     * 檢查長連線的各種物件狀態是否正常,正常情況下無需再建立
     *
     * @return
     */
    public boolean checkConnectStatus() {
        if (connector != null && connector.isActive() && connectFuture != null && connectFuture.isConnected() && session != null && session.isConnected()) {
            return true;
        } else {
            return false;
        }
    }

    public boolean connectIsNull() {
        return connector != null;
    }

    /**
     * 建立長連線,配置過濾器鏈和心跳工廠
     */
    public synchronized void crateLongConnect() {
        // 如果是長連線正在建立中
        if (isConnecting) {
            L.i("長連線正在建立中...");
            return;
        }
        if (!Config.isNetworkConnected(context)) {
            L.i("檢測到網路未開啟,無法正常啟動長連線,直接return...");
            return;
        }
        // 檢查長連線的各種物件狀態是否正常,正常情況下無需再建立
        if (checkConnectStatus()) {
            return;
        }
        isConnecting = true;
        try {
            connector = new NioSocketConnector();
            connector.setConnectTimeoutMillis(SOCKET_CONNECT_TIMEOUT);

            if (L.isDebug) {
                if (!connector.getFilterChain().contains("logger")) {
                    // 設定日誌輸出工廠
                    connector.getFilterChain().addLast("logger", new LoggingFilter());
                }
            }
            if (!connector.getFilterChain().contains("codec")) {
                // 設定請求和響應物件的編解碼操作
                connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new LongConnectProtocolFactory()));
            }
            // 建立心跳工廠
            ClientKeepAliveMessageFactory heartBeatFactory = new ClientKeepAliveMessageFactory();
            // 當讀操作空閒時傳送心跳
            KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory, IdleStatus.READER_IDLE);
            // 設定是否將事件繼續往下傳遞
            heartBeat.setForwardEvent(true);
            // 設定心跳包請求後超時無反饋情況下的處理機制,預設為關閉連線,在此處設定為輸出日誌提醒
            heartBeat.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.LOG);
            //設定心跳頻率
            heartBeat.setRequestInterval(KEEP_ALIVE_TIME_INTERVAL);
            if (!connector.getFilterChain().contains("keepAlive")) {
                connector.getFilterChain().addLast("keepAlive", heartBeat);
            }
            if (!connector.getFilterChain().contains("reconnect")) {
                // 設定長連線重連過濾器,當檢測到Session(會話)斷開後,重連長連線
                connector.getFilterChain().addLast("reconnect", new LongConnectReconnectionFilter());
            }
            // 設定接收和傳送緩衝區大小
            connector.getSessionConfig().setReceiveBufferSize(1024);
            connector.getSessionConfig().setSendBufferSize(1024);
            // 設定讀取空閒時間:單位為s
            connector.getSessionConfig().setReaderIdleTime(60);

            // 設定長連線業務邏輯處理類Handler
            LongConnectHandler longConnectHandler = new LongConnectHandler(this, context);
            connector.setHandler(longConnectHandler);

        } catch (Exception e) {
            e.printStackTrace();
            closeConnect();
        }

        startConnect();
    }

    /**
     * 開始或重連長連線
     */
    public synchronized void startConnect() {
        if (connector != null) {
            L.i("開始建立長連線...");
            boolean isSuccess = beginConnect();
            // 建立成功後,修改建立中狀態
            if (isSuccess) {
                isNeedRestart = false;
                if (context != null) {
                    // 長連線啟動成功後,主動拉取一次訊息
                    LoopRequest.getInstance(context).sendLoopRequest();
                }
            } else {
                // 啟動輪詢服務
                startLoopService();
            }
            isConnecting = false;
//            printProcessorExecutor();
        } else {
            L.i("connector已為null,不能執行建立連線動作...");
        }
    }

    /**
     * 檢測MINA中執行緒池的活動狀態
     */
    private void printProcessorExecutor() {
        Class connectorClass = connector.getClass().getSuperclass();
        try {
            L.i("connectorClass:" + connectorClass.getCanonicalName());
            Field field = connectorClass.getDeclaredField("processor");
            field.setAccessible(true);
            Object connectorObject = field.get(connector);
            if (connectorObject != null) {
                SimpleIoProcessorPool processorPool = (SimpleIoProcessorPool) connectorObject;
                Class processPoolClass = processorPool.getClass();
                Field executorField = processPoolClass.getDeclaredField("executor");
                executorField.setAccessible(true);
                Object executorObject = executorField.get(processorPool);
                if (executorObject != null) {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorObject;
                    L.i("執行緒池中當前執行緒數:" + threadPoolExecutor.getPoolSize() + "\t 核心執行緒數:" + threadPoolExecutor.getCorePoolSize() + "\t 最大執行緒數:" + threadPoolExecutor.getMaximumPoolSize());
                }

            } else {
                L.i("connectorObject = null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 開始建立Session
     *
     * @return
     */
    public boolean beginConnect() {

        if (session != null) {
            session.close(false);
            session = null;
        }
        if (connectFuture != null && connectFuture.isConnected()) {
            connectFuture.cancel();
            connectFuture = null;
        }
        FutureTask<Boolean> futureTask = new FutureTask<>(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                try {
                    InetSocketAddress address = new InetSocketAddress(NetworkTask.getBASEURL(), DEFAULT_PORT);
                    connectFuture = connector.connect(address);
                    connectFuture.awaitUninterruptibly(3000L);
                    session = connectFuture.getSession();
                    if (session == null) {
                        L.i(TAG + "連線建立失敗...當前環境:" + NetworkTask.getBASEURL());
                        return false;
                    } else {
                        L.i(TAG + "長連線已啟動,連線已成功...當前環境:" + NetworkTask.getBASEURL());
                        return true;
                    }
                } catch (Exception e) {
                    return false;
                }
            }
        });

        executorService.submit(futureTask);
        try {
            return futureTask.get();
        } catch (Exception e) {
            return false;
        }

    }

    /**
     * 關閉連線,根據傳入的引數設定session是否需要重新連線
     */
    public synchronized void closeConnect() {
        if (session != null) {
            session.close(false);
            session = null;
        }
        if (connectFuture != null && connectFuture.isConnected()) {
            connectFuture.cancel();
            connectFuture = null;
        }
        if (connector != null && !connector.isDisposed()) {
            // 清空裡面註冊的所以過濾器
            connector.getFilterChain().clear();
            connector.dispose();
            connector = null;
        }
        isConnecting = false;
        L.i("長連線已關閉...");
    }

    private volatile boolean isNeedRestart = false;

    public boolean isNeedRestart() {
        return isNeedRestart;
    }

    public void onEventMainThread(BaseEvent event) {
        if (event == null || TextUtils.isEmpty(event.getType()))
            return;
        if (EventBusConstant.EVENT_TYPE_NETWORK_STATUS.equals(event.getType())) {
            String status = (String) event.getExtraData();
            // 當網路狀態變化的時候請求startQuery介面
            if (status != null && status.equals("open")) {
                if (isNeedRestart && UserConfig.getUserInfo().getB3Key() != null && UserConfig.getUserInfo().getSessionKey() != null) {
                    L.i("檢測到網路已開啟且長連線處於關閉狀態,需要啟動長連線...");
                    Intent intent = new Intent(context, LongConnService.class);
                    intent.setAction(LongConnService.ACTION);
                    context.startService(intent);
                }
            }
        }
    }

    /**
     * 出現異常、session關閉後,接收事件進行長連線重連操作
     */
    public void onEventMainThread(LongConnectMessageEvent event) {

        if (event.getType() == LongConnectMessageEvent.TYPE_RESTART) {

            long currentTime = System.currentTimeMillis();

            // 票據有效的情況下進行重連長連線操作
            if (UserConfig.getUserInfo().getB3Key() != null && UserConfig.getUserInfo().getSessionKey() != null
                    && ((currentTime / 1000) < UserConfig.getUserInfo().getUnvalidSecs())) {
                // 等待2s後重新建立長連線
                SystemClock.sleep(1000);
                if (Config.isNetworkConnected(context)) {
                    L.i("出現異常情況,需要自動重連長連線...");
                    startConnect();
                } else {
                    isNeedRestart = true;
                    L.i("長連接出現異常,需要重新建立session會話...");
                }
            }
        } else if (event.getType() == LongConnectMessageEvent.TYPE_CLOSE) {
            L.i("收到session多次close的訊息,此時需要關閉長連線,等待下次鬧鐘服務來啟動...");
            closeConnect();
        }
    }


    /**
     * 啟動輪詢服務
     */
    public void startLoopService() {
        // 啟動輪詢服務
        // 暫時不考慮加入網路情況的判斷...
        if (!LoopService.isServiceRuning) {
            // 使用者是登入態,啟動輪詢服務
            if (UserConfig.isPassLogined()) {
                // 判斷當前長連線的狀態,若長連線已連線,則不再開啟輪詢服務
                if (MinaLongConnectManager.session != null && MinaLongConnectManager.session.isConnected()) {
                    LoopService.quitLoopService(context);
                    return;
                }
                LoopService.startLoopService(context);
            } else {
                LoopService.quitLoopService(context);
            }
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 相關推薦

    android連線實現

    本文中我們將講解一下App的長連線實現。一般而言長連線已經是App的標配了,推送功能的實現基礎就是長連線,當然了我們也可以通過輪訓操作實現推送功能,但是輪訓一般及時性比較差,而且網路消耗與電量銷燬比較多,因此一般推送功能都是通過長連線實現的。 那麼如何實現長連線呢?現在

    使用mina實現Android連線

    一.概述 android長連線的實現有很多種,最常用的是使用第三方的長連線,比如推送服務的實現.使用第三方的長連線雖然在實現上最簡單,但是擴充套件性缺少最差,要受限於三方的api,所以在這裡介紹使用mina來實現android的長連線服務.

    Android 基於Socket的連線實現一個實時推送的功能

    實現此功能需要考慮的幾點: 1)如何保證Socket長連線一直存在並有效執行 2)通過Service執行Socket,當服務端有資料時,通過廣播或者handler來更新UI 具體效果,來上程式碼: @Override public void run() { try

    android連線心跳機制

    在寫之前,我們首先了解一下為什麼android維護長連線需要心跳機制,首先我們知道,維護任何一個長連線都需要心跳機制,客戶端傳送一個心跳給 伺服器,伺服器給客戶端一個心跳應答,這樣就形成客戶端伺服器的一次完整的握手,這個握手是讓雙方都知道他們之間的連線是沒有斷開,客戶端

    tomcat websocket 連線實現

    1:首先在web.xml中配置Servlet  login.do對應MyWebSocketServlet MyWebSocketServlet程式碼如下: package com.socket; import javax.servlet.http.HttpServletR

    Android 連線初體驗(基於netty)

    前言 眾所周知,推送和 IM 在 Android 應用中很常見,但真正自己去實現的比較少,我們大多會去選擇第三方提供的成熟方案,如極光推送、雲信等,因為行動網路具有不確定性,因此自己實現一套穩定的方案會耗費很多精力,這對於小公司來說是得不償失的。 推送和 IM 我們平時用的很多,但真正瞭

    關於android連線及休眠喚醒的幾篇文章

    極光推送技術原理:無線網路長連線 移動網際網路應用現狀 因為手機平臺本身、電量、網路流量的限制,移動網際網路應用在設計上跟傳統 PC 上的應用很大不一樣,需要根據手機本身的特點,儘量的節省電量和流量,同時又要儘可能的保證資料能及時到達客戶端。 為了解決資料同步的問題,

    基於iframe的HTTP連線實現

    view plaincopy to clipboardprint?<html:form action="/myAction" target="myiframe">      <%-- 這裡寫你的頁面程式碼 --%>          <cent

    Spring系列文章 | SockJS連線實現一對一和一對多通訊

    最近專案上要做掃碼登入,所以研究了一下Spring WebSocket。網上找了很多資料 springmvc(18)使用WebSocket 和 STOMP 實現訊息功能、spring websocket + stomp 實現廣播通訊和一對一通訊,要麼就是不是自己想

    Android實現Socket連線 , OkSocket框架簡單使用

    一個Android輕量級Socket通訊框架,既OkHttp後又一力作. 框架開源地址: https://github.com/xuuhaoo/OkSocket OkSocket簡介 Android OkSocket是一款基於阻塞式傳統Socket的一款Socket客戶端整體解決方案.您

    如何實現android和伺服器保持連線

                這種功能實際上就是資料同步,同時要考慮手機本身、電量、網路流量等等限制因素,所以通常在移動端上有一下兩個解決方案:   1.一種是定時去server查詢資料,通常是使用HTTP協議來訪問web伺服器,稱Polli

    Android推送的核心原理:連線的簡單實現

    實際需求 移動端需要實時的獲取伺服器的資料 解決方案 輪詢方式:應用程式開啟定時的輪詢,不停的向伺服器請求資料。 SMS push:傳送二進位制簡訊到移動終端,來達到通知終端的目的。客戶端攔截這類簡訊,然後採取相應的操作 持久連線方式:應用程式與伺服

    Android之通過socket.io實現連線

    在專案開發中,時常有服務端向客戶端主動發起交流的需求,可以整合極光推送,但是如果網路不好的情況下,推送可能會遲遲收不到,這樣就導致了使用者體驗得不到保證。 若改用socket實現長連線的話,速度就快很

    Android TCP連線 心跳機制及實現

    維護任何一個長連線都需要心跳機制,客戶端傳送一個心跳給伺服器,伺服器給客戶端一個心跳應答, 這樣雙方都知道他們之間的連線是沒有斷開。【客戶端先發送給服務端】 如果超過一個時間的閾值,客戶端沒有收到伺服器的應答,或者伺服器沒有收到客戶端的心跳, 那麼對

    Android 使用Socket實現伺服器與手機客戶端的連線

    一、傳送請求的資訊: 1、介面 public interface Request { String getData(); } 2、文字請求: public class TextRequest implements Request{

    Socket連線Android端心跳機制實現

    1. 把socket連結和心跳功能都放在一個Service中,為什麼要放在Service中? 一般我們這種socket幾乎是跟app的生命週期一樣長,甚至更長。不管在不在Service中去完成操作,我們都得開非同步執行緒,雖然Service並不是

    基於Socket的TCP連線(服務端Java+客戶端Android),Service配合AIDL實現

    最近公司的專案要求加入訊息推送功能,由於專案使用者量不是很大,推送需求不是很嚴格,而且是基於內網的推送,所以我捨棄了使用三方的推送服務,自己使用Socket寫了推送功能,剪出一個小Demo來跟大家分享一下,有不足之處希望讀者能夠多多給出建議。 關於Socket的

    Mina連線框架實現Android客戶端與伺服器端通訊

    一、概述         Apache Mina Server 是一個網路通訊應用框架,也就是說,它主要是對基於TCP/IP、UDP/IP協議棧的通訊框架(當然,也可以提供JAVA 物件的序列化服務、虛擬機器管道通訊服務等),Mina 可以幫助我們快速開發高效能、高擴充套件

    Android時間定時任務實現

    col 啟動 cast 廣播 詳細 ref 定時任務 exce not 在服務的onStartCommand方法裏面使用AlarmManager 定時喚醒發送廣播,在廣播裏面啟動服務   每次執行startService方法啟動服務都會執行onStartCommand

    連線是如何實現的(不看後悔,一看必懂)

      在HTTP1.0和HTTP1.1協議中都有對長連線的支援。其中HTTP1.0需要在request中增加”Connection: keep-alive“ header才能夠支援,而HTTP1.1預設支援.  http1.0請求與服務端的互動過程: &nbs