Commit 2bf648c3 by 王宇航

可以通過調用GingerSoftConnect.connect連接服務器並發送數據

parent 941f086c
......@@ -3,7 +3,20 @@
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State />
<State>
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="9X4TRG5PSCEYZHZX" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-05-24T09:32:50.146130200Z" />
</State>
</entry>
</value>
</component>
......
......@@ -36,10 +36,11 @@ android {
}
dependencies {
implementation("com.squareup.okhttp3:okhttp:3.14.9")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation(project(":mylibrary"))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
......
......@@ -2,15 +2,34 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.GingersoftConnect"
tools:targetApi="31" />
tools:targetApi="31">
<activity
android:name="com.example.demo.MainActivity"
android:exported="true">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
package com.example.demo
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import com.example.gingersoft_connect.R
import com.gingersoft.connect.SendCallback
import com.gingersoft.connect.bean.Action
import com.gingersoft.connect.bean.MessageBuilder
import com.gingersoft.connect.bean.MessageSender
import com.gingersoft.connect.bean.OrderInfoBean
import com.gingersoft.connect.utils.GingerSoftConnect
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var msgSender: MessageBuilder? = null
var connect: GingerSoftConnect? = null
val tvConnect = findViewById<TextView>(R.id.tv_connect)
val tvDisconnect = findViewById<TextView>(R.id.tv_disconnect)
val tvSendMsg = findViewById<TextView>(R.id.tv_send_msg)
val tvSendValue = findViewById<TextView>(R.id.tv_send_value)
tvConnect.setOnClickListener {
tvConnect.isClickable = false
connect = GingerSoftConnect()
msgSender = connect!!.connect(
"192.168.1.151",
12581,
object : GingerSoftConnect.SocketStateListener {
override fun onOpen() {
super.onOpen()
runOnUiThread {
tvConnect.text = "已連接"
tvConnect.isClickable = true
}
}
override fun onClose(code: Int, reason: String?, remote: Boolean) {
super.onClose(code, reason, remote)
runOnUiThread {
tvConnect.text = "已斷開:$code,$reason"
tvConnect.isClickable = true
}
}
override fun onError(ex: Exception?) {
super.onError(ex)
runOnUiThread {
tvConnect.isClickable = true
tvConnect.text = "發生錯誤:${ex?.message}"
}
}
})
}
tvDisconnect.setOnClickListener {
connect?.disconnect()
}
tvSendMsg.setOnClickListener {
msgSender?.initSendData(Action.KitchenInfo, OrderInfoBean())
?.asyncSend(object : SendCallback {
override fun callback(status: Boolean, errorCode: Int) {
runOnUiThread {
tvSendValue.text = if (status) "發送成功" else when (errorCode) {
MessageBuilder.ERROR_CODE_SEND_TIMEOUT -> "發送消息超時"
MessageBuilder.ERROR_CODE_NOT_CONNECT -> "未連接到服務器"
MessageBuilder.ERROR_CODE_CONNECT_TIMEOUT -> "連接服務器超時"
else -> "發生錯誤:$errorCode"
}
}
}
})
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/purple_700"
android:paddingHorizontal="20dp"
android:paddingVertical="15dp"
android:text="連接服務器"
android:textColor="@color/white"
android:textSize="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@color/purple_700"
android:paddingHorizontal="20dp"
android:paddingVertical="15dp"
android:text="斷開服務器"
android:textColor="@color/white"
android:textSize="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_send_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@color/purple_700"
android:paddingHorizontal="20dp"
android:paddingVertical="15dp"
android:text="發送 消息"
android:textColor="@color/white"
android:textSize="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_send_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingHorizontal="20dp"
android:paddingVertical="15dp"
android:textColor="@color/black"
android:textSize="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
\ No newline at end of file
......@@ -34,13 +34,17 @@ android {
}
dependencies {
implementation("androidx.core:core-ktx:1.10.1")
implementation("org.jmdns:jmdns:3.5.5")
implementation("org.java-websocket:Java-WebSocket:1.5.2")
implementation("org.nanohttpd:nanohttpd-websocket:2.3.1")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("com.google.android.material:material:1.12.0")
implementation("com.squareup.okhttp3:okhttp:3.14.9")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation("com.google.code.gson:gson:2.10.1")
}
afterEvaluate {
......
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:networkSecurityConfig="@xml/network_security_config" />
</manifest>
\ No newline at end of file
package com.gingersoft.connect
interface SendCallback {
fun callback(status: Boolean, errorCode: Int)
}
\ No newline at end of file
package com.gingersoft.connect.bean
enum class Action {
KitchenInfo, SoldOutInfo
}
\ No newline at end of file
package com.gingersoft.connect.bean;
public class FoodInfoBean {
private Long id;
/**
* 食品id
*/
private String FoodId;
/**
* 打印用的id(RicePOS的prjId)
*/
private String PrintId;
/**
* 訂單ID
*/
private Long orderId;
/**
* 食品名稱
*/
private String FoodName;
/**
* 食品數量
*/
private String quantity;
/**
* 食品金額
*/
private double price;
/**
* 食品類型
*/
private int type;
/**
* 父級食品id
*/
private String parentId;
/**
* 食品是否打印紅色字
* true 首頁也會顯示紅色 false 首頁顯示設置頁面的顏色
*/
private boolean isPrintRedLetter;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getFoodId() {
return this.FoodId;
}
public void setFoodId(String FoodId) {
this.FoodId = FoodId;
}
public String getPrintId() {
return this.PrintId;
}
public void setPrintId(String PrintId) {
this.PrintId = PrintId;
}
public Long getOrderId() {
return this.orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
public String getFoodName() {
return this.FoodName;
}
public void setFoodName(String FoodName) {
this.FoodName = FoodName;
}
public String getQuantity() {
return this.quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public double getPrice() {
return this.price;
}
public void setPrice(double price) {
this.price = price;
}
public int getType() {
return this.type;
}
public void setType(int type) {
this.type = type;
}
public String getParentId() {
return this.parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public boolean getIsPrintRedLetter() {
return this.isPrintRedLetter;
}
public void setIsPrintRedLetter(boolean isPrintRedLetter) {
this.isPrintRedLetter = isPrintRedLetter;
}
}
package com.gingersoft.connect.bean
class MessageBean<T>(
/**
* 消息唯一ID,發送消息過去,服務端收到後會發送一條成功接收消息,通過這個code來區分是哪條消息
*/
var code: Int = 0,
var action: String? = null,
var data: T? = null
)
\ No newline at end of file
package com.gingersoft.connect.bean
import com.gingersoft.connect.utils.GingerSoftConnect
import com.gingersoft.connect.utils.MyWebSocketClient
import java.util.concurrent.atomic.AtomicInteger
class MessageBuilder(
private val connect: GingerSoftConnect,
private val webSocketClient: MyWebSocketClient
) {
companion object {
private val msgCode = AtomicInteger(0)
const val ERROR_CODE_SEND_TIMEOUT = 100
const val ERROR_CODE_NOT_CONNECT = 101
const val ERROR_CODE_CONNECT_TIMEOUT = 102
}
fun initSendData(action: Action, sendData: SendMsgType): MessageSender {
val currentMsgCode = msgCode.incrementAndGet()
val msg = MessageBean(currentMsgCode, action.toString(), sendData)
return MessageSender(connect, webSocketClient, msg)
}
}
\ No newline at end of file
package com.gingersoft.connect.bean
import android.os.Build.VERSION_CODES.P
import android.util.Log
import com.gingersoft.connect.SendCallback
import com.gingersoft.connect.utils.GingerSoftConnect
import com.gingersoft.connect.utils.GsonUtils
import com.gingersoft.connect.utils.MyWebSocketClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class MessageSender(
private val connect: GingerSoftConnect,
private val webSocketClient: MyWebSocketClient,
private val msg: MessageBean<*>
) {
fun send(): GingerSoftConnect {
asyncSend(null)
return connect
}
/**
* 發送數據到服務器
* @param callback Function1<Boolean, Unit> 回調,只能保證是否發送,不能保證對方是否接收到
* @return GingerSoftConnect
*/
fun send(callback: (Boolean) -> Unit): GingerSoftConnect {
if (webSocketClient.isOpen) {
asyncSend(null)
callback.invoke(true)
} else {
callback.invoke(false)
}
return connect
}
/**
* 發送到服務器,對方正常接收到數據會通知過來
* @return GingerSoftConnect
*/
fun asyncSend(callback: SendCallback?): GingerSoftConnect {
val currentTimeMillis = System.currentTimeMillis()
runBlocking {
launch(Dispatchers.IO) {
while (webSocketClient.getStatus() == 0 && System.currentTimeMillis() - currentTimeMillis < 10000) {
delay(500)
}
if (webSocketClient.getStatus() != 0) {
send(callback)
} else {
// 超時
callback?.callback(false, MessageBuilder.ERROR_CODE_CONNECT_TIMEOUT)
}
}
}
return connect
}
private fun send(callback: SendCallback?) {
if (webSocketClient.isClosed || webSocketClient.isClosing || !webSocketClient.isOpen) {
callback?.callback(false, MessageBuilder.ERROR_CODE_NOT_CONNECT)
} else {
webSocketClient.sendMsg(msg.code.toString(), GsonUtils.GsonString(msg), callback)
}
}
}
\ No newline at end of file
package com.gingersoft.connect.bean;
import java.util.List;
public class OrderInfoBean implements SendMsgType {
private Long id;
/**
* 訂單ID
*/
private Long orderId;
/**
* 訂單類型
*/
private int orderType;
/**
* 用餐人數
*/
private int pax;
/**
* 送單人id
*/
private String senderId;
/**
* 送單人名稱
*/
private String senderName;
/**
* 送單時間
*/
private String sendTime;
/**
* 發送數據的設備id
*/
private String sendDeviceId;
/**
* 發送數據的設備名稱
*/
private String sendDeviceName;
/**
* 送單次數
*/
private int sendOrderCount;
/**
* 是否首次送單
*/
private boolean isFirstSendOrder;
/**
* 飛單描述,例如本機為k2,POS機從k1打印失敗,轉到K2打印,可以在此字段中寫K1->K2
*/
private String flyPrintInfo;
/**
* 打印狀態
*/
private int printStatus;
/**
* 食品信息
*/
private List<FoodInfoBean> foodInfoBeanList;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getOrderId() {
return this.orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
public int getOrderType() {
return this.orderType;
}
public void setOrderType(int orderType) {
this.orderType = orderType;
}
public int getPax() {
return this.pax;
}
public void setPax(int pax) {
this.pax = pax;
}
public String getSenderId() {
return this.senderId;
}
public void setSenderId(String senderId) {
this.senderId = senderId;
}
public String getSenderName() {
return this.senderName;
}
public void setSenderName(String senderName) {
this.senderName = senderName;
}
public String getSendTime() {
return this.sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getSendDeviceId() {
return this.sendDeviceId;
}
public void setSendDeviceId(String sendDeviceId) {
this.sendDeviceId = sendDeviceId;
}
public String getSendDeviceName() {
return this.sendDeviceName;
}
public void setSendDeviceName(String sendDeviceName) {
this.sendDeviceName = sendDeviceName;
}
public int getSendOrderCount() {
return this.sendOrderCount;
}
public void setSendOrderCount(int sendOrderCount) {
this.sendOrderCount = sendOrderCount;
}
public boolean getIsFirstSendOrder() {
return this.isFirstSendOrder;
}
public void setIsFirstSendOrder(boolean isFirstSendOrder) {
this.isFirstSendOrder = isFirstSendOrder;
}
public String getFlyPrintInfo() {
return this.flyPrintInfo;
}
public void setFlyPrintInfo(String flyPrintInfo) {
this.flyPrintInfo = flyPrintInfo;
}
public int getPrintStatus() {
return this.printStatus;
}
public void setPrintStatus(int printStatus) {
this.printStatus = printStatus;
}
}
package com.gingersoft.connect.bean
/**
* 只是用來限制,可以傳什麼類型的參數
*/
interface SendMsgType
\ No newline at end of file
//package com.gingersoft.connect.utils
//
//import android.content.Context
//import android.net.wifi.WifiManager
//import android.util.Log
//import java.io.IOException
//import java.net.InetAddress
//import javax.jmdns.JmDNS
//import javax.jmdns.ServiceEvent
//import javax.jmdns.ServiceInfo
//import javax.jmdns.ServiceListener
//
//object DeviceDiscovery {
//
// var jmdns: JmDNS? = null
// fun discoverDevices(context: Context, port: Int, callback: (String, Int) -> Unit) {
// try {
// val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
// val multicastLock = wifiManager.createMulticastLock("myMulticastLock")
// multicastLock.setReferenceCounted(true)
// multicastLock.acquire() // 開啟多播鎖可以快速接收消息,但是會增加耗電量
// val address = getLocalIpAddress(context)
// if (address != null) {
// jmdns = JmDNS.create(address)
// val serviceInfo =
// ServiceInfo.create("_ws._tcp.local.", "gingersoft", port, "path=index.html")
// jmdns?.registerService(serviceInfo)
// jmdns?.addServiceListener("_ws._tcp.local.", object : ServiceListener {
// override fun serviceAdded(event: ServiceEvent) {
// Log.e("eeeaaa", "Service added:${event.info}}")
// }
//
// override fun serviceRemoved(event: ServiceEvent) {
// Log.e("eeeaaa", "Service removed: ${event.info}")
// }
//
// override fun serviceResolved(event: ServiceEvent) {
// val hostAddress = event.info.hostAddresses[0]
// val port = event.info.port
// Log.e("eeeaaa", "serviceResolved: ${event.info}---${hostAddress}---${address.hostAddress}")
// if (event.info.name.contains("gingersoft") && hostAddress != null && hostAddress != address.hostAddress) {
// Log.e("eeeaaa", "Service resolved: ${event.info} at $hostAddress:$port")
// callback(hostAddress, port)
// }
// // 超過多久搜索不到,關閉多播鎖
//// multicastLock.release()
// }
// })
// } else {
// Log.e("eeeaaa", "Failed to get local IP address")
// }
// } catch (e: IOException) {
// e.printStackTrace()
// }
// }
//
// private fun getLocalIpAddress(context: Context): InetAddress? {
// try {
// val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
// val wifiInfo = wifiManager.connectionInfo
// val ipAddress = wifiInfo.ipAddress
// val ipByteArray = byteArrayOf(
// (ipAddress and 0xff).toByte(),
// (ipAddress shr 8 and 0xff).toByte(),
// (ipAddress shr 16 and 0xff).toByte(),
// (ipAddress shr 24 and 0xff).toByte()
// )
// return InetAddress.getByAddress(ipByteArray)
// } catch (e: Exception) {
// e.printStackTrace()
// }
// return null
// }
//
//
// fun stopService() {
// if (jmdns != null) {
// jmdns!!.unregisterAllServices()
// try {
// jmdns!!.close()
// } catch (e: IOException) {
// e.printStackTrace()
// }
// }
// }
//}
\ No newline at end of file
package com.gingersoft.connect.utils
import com.gingersoft.connect.bean.MessageBuilder
import java.net.URI
class GingerSoftConnect {
private var webSocketClient: MyWebSocketClient? = null
fun connect(ip: String, port: Int, listener: SocketStateListener?): MessageBuilder {
val uri = URI("ws://$ip:$port")
webSocketClient = MyWebSocketClient(uri, listener)
webSocketClient?.connect()
// 連接成功後獲得發送類
return MessageBuilder(this, webSocketClient!!)
}
fun disconnect() {
webSocketClient?.close()
}
interface SocketStateListener {
fun onOpen() {}
fun onClose(code: Int, reason: String?, remote: Boolean) {}
fun onError(ex: Exception?) {}
}
}
\ No newline at end of file
package com.gingersoft.connect.utils;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GsonUtils {
private static volatile Gson gson;
public static Gson getGson() {
if (gson == null) {
synchronized (GsonUtils.class) {
if (gson == null) {
gson = new Gson();
}
}
}
return gson;
}
public static void init(Gson gson) {
GsonUtils.gson = gson;
}
private GsonUtils() {
}
/**
* 轉成json
*
* @param object
* @return
*/
public static String GsonString(Object object) {
String gsonString = null;
try {
gsonString = getGson().toJson(object);
} catch (Exception e) {
e.printStackTrace();
}
return gsonString;
}
/**
* 轉成bean
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
T t = null;
try {
t = getGson().fromJson(gsonString, cls);
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
/**
* 轉成bean
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(Object gsonString, Class<T> cls) {
return GsonToBean(GsonString(gsonString), cls);
}
/**
* json字符串轉成list
*
* @param cls
* @return
*/
public static <T> ArrayList<T> jsonToList(Object object, Class<T> cls) {
return jsonToList(GsonString(object), cls);
}
/**
* json字符串轉成list
*
* @param cls
* @return
*/
public static <T> ArrayList<T> jsonToList(String json, Class<T> cls) {
ArrayList<T> mList = new ArrayList<>();
if (json == null || json.isEmpty()) {
return null;
}
try {
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for (final JsonElement elem : array) {
mList.add(getGson().fromJson(elem, cls));
}
} catch (Exception e) {
e.printStackTrace();
}
return mList;
}
/**
* 轉成list中有map的
*
* @param gsonString
* @return
*/
public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
List<Map<String, T>> list = null;
list = getGson().fromJson(gsonString,
new TypeToken<List<Map<String, T>>>() {
}.getType());
return list;
}
/**
* 轉成map的
*
* @param gsonString
* @return
*/
public static <T> Map<String, T> GsonToMaps(String gsonString) {
Map<String, T> map = null;
map = getGson().fromJson(gsonString, new TypeToken<Map<String, T>>() {
}.getType());
return map;
}
}
package com.gingersoft.connect.utils
import android.util.Log
import com.gingersoft.connect.SendCallback
import com.gingersoft.connect.bean.MessageBuilder
import kotlinx.coroutines.channels.Channel
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import java.net.URI
import java.util.Timer
import java.util.TimerTask
class MyWebSocketClient(
serverUri: URI,
private val listener: GingerSoftConnect.SocketStateListener?
) :
WebSocketClient(serverUri) {
private val map by lazy { HashMap<String, SendCallback>() }
private val timerMap by lazy { HashMap<String, Timer>() }
private var status = 0
override fun onOpen(handshakedata: ServerHandshake?) {
listener?.onOpen()
status = 1
}
override fun onMessage(message: String?) {
Log.e("eeeaaa", "客戶端收到消息:$message")
if (message != null && map.containsKey(message)) {
map[message]?.callback(true, 200)
timerMap[message]?.cancel()
}
}
override fun onClose(code: Int, reason: String?, remote: Boolean) {
listener?.onClose(code, reason, remote)
status = 2
}
override fun onError(ex: Exception?) {
listener?.onError(ex)
status = 3
}
fun sendMsg(msgCode: String, text: String, callback: SendCallback?) {
if (callback != null) {
// 保存code和callback的關係,服務器返回收到後,需要調用回調
// 使用map是為了應對多線程情況
map[msgCode] = callback
// 增加十秒倒計時,超時情況
timerMap[msgCode] = Timer()
timerMap[msgCode]?.schedule(object : TimerTask() {
override fun run() {
callback.callback(false, MessageBuilder.ERROR_CODE_SEND_TIMEOUT)
}
}, 10000)
}
// 發送數據到服務器
send(text)
}
fun getStatus() = status
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment