論壇問題: https://ask.dcloud.net.cn/question/74505
使用: uni.connectSocket(OBJECT) 和 SocketTask.onOpen(CALLBACK) 在安卓手機無法觸發websocket的open方法
解決辦法使用plus-websocket插件
https://ext.dcloud.net.cn/plugin?id=647
注意方法使用:
socket.connectSocket(OBJECT)
- socket.onSocketOpen(CALLBACK)
- socket.onSocketError(CALLBACK)
- socket.sendSocketMessage(OBJECT)
- socket.onSocketMessage(CALLBACK)
- socket.closeSocket(OBJECT)
- socket.onSocketClose(CALLBACK)
轉載大佬的插件案例: https://www.jianshu.com/p/241fd3a81c3f
/**uni websocket工具類*/ //npm i plus-websocket --save import socket from 'plus-websocket' export default class websocket { constructor({ heartCheck, isReconnection }) { // 是否連接 this._isLogin = false; // 當前網絡狀態 this._netWork = true; // 是否人為退出 this._isClosed = false; // 心跳檢測頻率 this._timeout = 3000; this._timeoutObj = null; // 當前重連次數 this._connectNum = 0; // 心跳檢測和斷線重連開關,true為啟用,false為關閉 this._heartCheck = heartCheck; this._isReconnection = isReconnection; // this._onSocketOpened(); } // 心跳重置 _reset() { clearTimeout(this._timeoutObj); return this; } // 心跳開始 _start() { let _this = this; this._timeoutObj = setInterval(() => { //發送心跳 _this.sendHeartbeatData(); }, this._timeout); } // 監聽websocket連接關閉 onSocketClosed(options) { socket.onSocketClose(err => { console.log('當前websocket連接已關閉,錯誤信息為:' + JSON.stringify(err)); // 停止心跳連接 if (this._heartCheck) { this._reset(); } // 關閉已登錄開關 this._isLogin = false; // 檢測是否是用戶自己退出小程序 if (!this._isClosed) { // 進行重連 if (this._isReconnection) { this._reConnect(options) } } }) } // 檢測網絡變化 onNetworkChange(options) { uni.onNetworkStatusChange(res => { console.log('當前網絡狀態:' + res.isConnected); if (!this._netWork) { this._isLogin = false; // 進行重連 if (this._isReconnection) { this._reConnect(options) } } }) } _onSocketOpened() { socket.onSocketOpen(res => { console.log('【websocket】已打開'); // 打開已登錄開關 this._isLogin = true; // 發送心跳 if (this._heartCheck) { this._reset()._start(); } // 發送登錄信息 this.sendLoginData(); // 打開網絡開關 this._netWork = true; }) } // 接收服務器返回的消息 onReceivedMsg(callBack) { socket.onSocketMessage(event => { let msg = this.socketEventDataToStr(event) // console.log(msg); if (typeof callBack == "function") { callBack(msg) } else { console.log('參數的類型必須為函數') } }) } // 建立websocket連接 initWebSocket(options) { let _this = this; if (this._isLogin) { console.log("您已經登錄了"); } else { // 檢查網絡 uni.getNetworkType({ success(result) { if (result.networkType != 'none') { // 開始建立連接 console.log('建立websocket連接' + options.url); socket.connectSocket({ url: options.url, success(res) { if (typeof options.success == "function") { options.success(res) _this._onSocketOpened(); } else { console.log('參數的類型必須為函數') } }, fail(err) { if (typeof options.fail == "function") { options.fail(err) } else { console.log('參數的類型必須為函數') } } }) } else { console.log('網絡已斷開'); _this._netWork = false; // 網絡斷開后顯示model uni.showModal({ title: '網絡錯誤', content: '請重新打開網絡', showCancel: false, success: function(res) { if (res.confirm) { console.log('用戶點擊確定') } } }) } } }) } } // 發送websocket消息 sendWebSocketMsg(options) { this.sendBinary(1,options); } //發送心跳連接 sendHeartbeatData() { this.sendBinary(99, { data: {}, success(res) { console.log('【websocket】心跳連接成功') }, fail(err) { console.log('【websocket】心跳連接失敗') console.log(err) } }); } //發送第一次連接數據 sendLoginData() { this.sendBinary(99, { data: {}, success(res) { console.log('【websocket】第一次連接成功') }, fail(err) { console.log('【websocket】第一次連接失敗') console.log(err) } }); // this.sendBinary(99, {}); // socket.sendSocketMessage({ // // 這里是第一次建立連接所發送的信息,應由前后端商量后決定 // data: JSON.stringify({ // "key": 'value' // }) // }) } // 重連方法,會根據時間頻率越來越慢 _reConnect(options) { let timer, _this = this; if (this._connectNum < 20) { timer = setTimeout(() => { this.initWebSocket(options) }, 3000) this._connectNum += 1; } else if (this._connectNum < 50) { timer = setTimeout(() => { this.initWebSocket(options) }, 10000) this._connectNum += 1; } else { timer = setTimeout(() => { this.initWebSocket(options) }, 450000) this._connectNum += 1; } } // 關閉websocket連接 closeWebSocket() { socket.closeSocket(); this._isClosed = true; } //發送二進制 sendBinary(commendType, options) { let sendMsg = options.data let uint8Array = new TextEncoder().encode(JSON.stringify(sendMsg)); let byteArr = new ArrayBuffer(4 + uint8Array.length); //DataView有三個參數,后兩個可以缺省;每一個要是ArrayBuffer對象或SharedArrayBuffer對象 let dv = new DataView(byteArr); dv.setUint32(0, commendType, false); for (let i = 0; i < uint8Array.length; i++) { dv.setUint8(4 + i, uint8Array[i]); } // console.log(dv); socket.sendSocketMessage({ data: dv.buffer, success(res) { if (typeof options.success == "function") { options.success(res) } else { console.log('參數的類型必須為函數') } }, fail(err) { if (typeof options.fail == "function") { options.fail(err) } else { console.log('參數的類型必須為函數') } } }); } //轉化方法 socketEventDataToStr(event) { let dv = new DataView(event.data); let commendType = dv.getUint32(0, true); let slice = event.data.slice(4, event.data.length); let unit8Arr = new Uint8Array(slice); let s = new TextDecoder("utf-8").decode(unit8Arr); console.log("【websocket】標志位:" + commendType); console.log("【websocket】返回信息:" + s); return s; } }
