diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
deleted file mode 100644
index e7ebe2f..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-interface ISocketConnectionListener {
-
- /**
- * Socket连接状态
- * */
- fun onServiceStatusConnectChanged(state: ConnectionState)
-
- /**
- * Socket数据
- * */
- fun onMessageResponse(bytes: ByteArray?)
-}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
deleted file mode 100644
index e7ebe2f..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-interface ISocketConnectionListener {
-
- /**
- * Socket连接状态
- * */
- fun onServiceStatusConnectChanged(state: ConnectionState)
-
- /**
- * Socket数据
- * */
- fun onMessageResponse(bytes: ByteArray?)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
new file mode 100644
index 0000000..aeb3ac0
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
@@ -0,0 +1,8 @@
+package com.casic.app.safetreecontroller.tcp
+
+interface OnSocketConnectionListener {
+ fun onConnected()
+ fun onDisconnected()
+ fun onError(t: Throwable)
+ fun onMessageReceived(bytes: ByteArray?)
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
deleted file mode 100644
index e7ebe2f..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-interface ISocketConnectionListener {
-
- /**
- * Socket连接状态
- * */
- fun onServiceStatusConnectChanged(state: ConnectionState)
-
- /**
- * Socket数据
- * */
- fun onMessageResponse(bytes: ByteArray?)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
new file mode 100644
index 0000000..aeb3ac0
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
@@ -0,0 +1,8 @@
+package com.casic.app.safetreecontroller.tcp
+
+interface OnSocketConnectionListener {
+ fun onConnected()
+ fun onDisconnected()
+ fun onError(t: Throwable)
+ fun onMessageReceived(bytes: ByteArray?)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
deleted file mode 100644
index 23b5cc0..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-import io.netty.channel.ChannelHandlerContext
-import io.netty.channel.SimpleChannelInboundHandler
-
-class SocketChannelHandler(private val listener: ISocketConnectionListener) :
- SimpleChannelInboundHandler() {
-
- override fun channelActive(ctx: ChannelHandlerContext) {
- super.channelActive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.CONNECTED)
- }
-
- override fun channelInactive(ctx: ChannelHandlerContext) {
- super.channelInactive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.DISCONNECTED)
- }
-
- override fun channelRead0(ctx: ChannelHandlerContext, data: ByteArray?) {
- listener.onMessageResponse(data)
- }
-
- override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
- super.exceptionCaught(ctx, cause)
- cause.printStackTrace()
- ctx.close()
- listener.onServiceStatusConnectChanged(ConnectionState.ERROR)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
deleted file mode 100644
index e7ebe2f..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-interface ISocketConnectionListener {
-
- /**
- * Socket连接状态
- * */
- fun onServiceStatusConnectChanged(state: ConnectionState)
-
- /**
- * Socket数据
- * */
- fun onMessageResponse(bytes: ByteArray?)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
new file mode 100644
index 0000000..aeb3ac0
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
@@ -0,0 +1,8 @@
+package com.casic.app.safetreecontroller.tcp
+
+interface OnSocketConnectionListener {
+ fun onConnected()
+ fun onDisconnected()
+ fun onError(t: Throwable)
+ fun onMessageReceived(bytes: ByteArray?)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
deleted file mode 100644
index 23b5cc0..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-import io.netty.channel.ChannelHandlerContext
-import io.netty.channel.SimpleChannelInboundHandler
-
-class SocketChannelHandler(private val listener: ISocketConnectionListener) :
- SimpleChannelInboundHandler() {
-
- override fun channelActive(ctx: ChannelHandlerContext) {
- super.channelActive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.CONNECTED)
- }
-
- override fun channelInactive(ctx: ChannelHandlerContext) {
- super.channelInactive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.DISCONNECTED)
- }
-
- override fun channelRead0(ctx: ChannelHandlerContext, data: ByteArray?) {
- listener.onMessageResponse(data)
- }
-
- override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
- super.exceptionCaught(ctx, cause)
- cause.printStackTrace()
- ctx.close()
- listener.onServiceStatusConnectChanged(ConnectionState.ERROR)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
index 519b1ce..ef0b7e6 100644
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
@@ -6,68 +6,125 @@
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
+import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
+import io.netty.channel.EventLoopGroup
+import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.codec.bytes.ByteArrayDecoder
import io.netty.handler.codec.bytes.ByteArrayEncoder
import io.netty.handler.timeout.IdleStateHandler
+import java.util.concurrent.TimeUnit
-class TcpClient(private val socketConnectionListener: ISocketConnectionListener) {
+
+class TcpClient(
+ private val host: String,
+ private val port: Int,
+ private val listener: OnSocketConnectionListener
+) {
private val kTag = "TcpClient"
- private var nioEventLoopGroup: NioEventLoopGroup? = null
+ private val reconnectDelay = 5L
+ private var bootstrap: Bootstrap = Bootstrap()
+ private var loopGroup: EventLoopGroup = NioEventLoopGroup()
private var channel: Channel? = null
+ private var isRunning = false
- fun startConnectTcpServer(hostname: String, port: Int) {
- nioEventLoopGroup = NioEventLoopGroup()
- val bootstrap = Bootstrap()
- bootstrap.group(nioEventLoopGroup) //设置的一系列连接参数操作等
+ fun start() {
+ if (isRunning) {
+ return
+ }
+ bootstrap.group(loopGroup)
.channel(NioSocketChannel::class.java)
.option(ChannelOption.TCP_NODELAY, true) //无阻塞
.option(ChannelOption.SO_KEEPALIVE, true) //长连接
.option(
- ChannelOption.RCVBUF_ALLOCATOR,
- AdaptiveRecvByteBufAllocator(5000, 5000, 8000)
- ) //接收缓冲区 最小值太小时数据接收不全
- .handler(object : ChannelInitializer() {
- override fun initChannel(channel: SocketChannel) {
- val pipeline = channel.pipeline()
- //参数1:代表读套接字超时的时间,没收到数据会触发读超时回调;
- //参数2:代表写套接字超时时间,没进行写会触发写超时回调;
- //参数3:将在未执行读取或写入时触发超时回调,0代表不处理;
- //读超时尽量设置大于写超时,代表多次写超时时写心跳包,多次写了心跳数据仍然读超时代表当前连接错误,即可断开连接重新连接
- pipeline.addLast(IdleStateHandler(60, 10, 0))
- pipeline.addLast(ByteArrayDecoder())
- pipeline.addLast(ByteArrayEncoder())
- pipeline.addLast(SocketChannelHandler(socketConnectionListener))
- }
- })
- try {
- //连接监听
- val channelFuture = bootstrap.connect(hostname, port)
- .addListener(object : ChannelFutureListener {
- override fun operationComplete(channelFuture: ChannelFuture) {
- if (channelFuture.isSuccess) {
- channel = channelFuture.channel()
+ ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator(5000, 5000, 8000)
+ )
+ .handler(SimpleChannelInitializer())
+ connect()
+ }
+
+ private inner class SimpleChannelInitializer : ChannelInitializer() {
+ override fun initChannel(ch: SocketChannel?) {
+ ch?.apply {
+ pipeline()
+ .addLast(IdleStateHandler(60, 10, 0))
+ .addLast(ByteArrayDecoder())
+ .addLast(ByteArrayEncoder())
+ .addLast(object : SimpleChannelInboundHandler() {
+ override fun channelActive(ctx: ChannelHandlerContext?) {
+ Log.d(kTag, "channelActive: ")
+ listener.onConnected()
}
- }
- }).sync()
- // 等待连接关闭
- channelFuture.channel().closeFuture().sync()
- } catch (e: Exception) {
- e.printStackTrace()
+
+ override fun channelInactive(ctx: ChannelHandlerContext?) {
+ Log.d(kTag, "channelInactive: ")
+ listener.onDisconnected()
+ reconnect()
+ }
+
+ override fun channelRead0(
+ ctx: ChannelHandlerContext?, msg: ByteArray?
+ ) {
+ listener.onMessageReceived(msg)
+ }
+
+ override fun exceptionCaught(
+ ctx: ChannelHandlerContext, cause: Throwable
+ ) {
+ Log.d(kTag, "exceptionCaught: ${cause.message}")
+ listener.onError(cause)
+ ctx.close()
+ }
+ })
+ }
}
}
- fun sendCommand(bytes: ByteArray) {
- channel?.writeAndFlush(bytes)
+ private fun connect() {
+ if (channel != null && channel!!.isActive) {
+ return
+ }
+
+ Thread {
+ try {
+ val channelFuture = bootstrap.connect(host, port)
+ .addListener(object : ChannelFutureListener {
+ override fun operationComplete(channelFuture: ChannelFuture) {
+ if (channelFuture.isSuccess) {
+ isRunning = true
+ channel = channelFuture.channel()
+ }
+ }
+ }).sync()
+ // 等待连接关闭
+ channelFuture.channel().closeFuture().sync()
+ } catch (e: Exception) {
+ Log.d(kTag, "connect: ${e.message}")
+ reconnect()
+ }
+ }.start()
}
- fun disconnect() {
- Log.d(kTag, "disconnect ===> 断开连接")
- nioEventLoopGroup?.shutdownGracefully()
+ private fun reconnect() {
+ loopGroup.schedule({ connect() }, reconnectDelay, TimeUnit.SECONDS)
+ Log.d(kTag, "Reconnecting: ")
+ }
+
+ fun stop() {
+ isRunning = false
+ channel?.close()
+ loopGroup.shutdownGracefully()
+ }
+
+ fun sendMessage(bytes: ByteArray) {
+ if (!isRunning) {
+ return
+ }
+ channel?.writeAndFlush(bytes)
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bea2916..728f0b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,8 @@
+
+
@@ -31,5 +33,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
new file mode 100644
index 0000000..956ca38
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/ForegroundRunningService.kt
@@ -0,0 +1,91 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.Message
+import androidx.core.app.NotificationCompat
+import com.casic.app.safetreecontroller.R
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+
+class ForegroundRunningService : Service(), Handler.Callback {
+
+ companion object {
+ var weakReferenceHandler: WeakReferenceHandler? = null
+ }
+
+ private val kTag = "ForegroundRunningService"
+ private val notificationId = 1
+ private var notificationManager: NotificationManager? = null
+ private var notificationBuilder: NotificationCompat.Builder? = null
+
+ override fun onCreate() {
+ super.onCreate()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ // Android 8.0(API 级别 26)及以上版本需要创建通知渠道
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = "${resources.getString(R.string.app_name)}前台服务"
+ val channel = NotificationChannel(
+ "foreground_running_service_channel", name, NotificationManager.IMPORTANCE_HIGH
+ )
+ channel.description = "Channel for Foreground Running Service"
+ notificationManager?.createNotificationChannel(channel)
+ }
+ notificationBuilder = NotificationCompat.Builder(this, "foreground_running_service_channel")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle("安全树通讯服务连接中...")
+ .setContentText("为降低被系统杀死的概率,请勿关闭此通知")
+ .setPriority(NotificationCompat.PRIORITY_HIGH) // 设置通知优先级
+ .setOngoing(true)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+
+ val notification = notificationBuilder?.build()
+ startForeground(notificationId, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ weakReferenceHandler = WeakReferenceHandler(this)
+ return START_STICKY
+ }
+
+ override fun handleMessage(msg: Message): Boolean {
+ when (msg.what) {
+ 2024110501 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务已连接")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110502 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务断开连接,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+
+ 2024110503 -> {
+ notificationBuilder?.setContentTitle("安全树通讯服务连接出错,开始重连")
+ val notification = notificationBuilder?.build()
+ notificationManager?.notify(notificationId, notification)
+ }
+ }
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ } else {
+ stopForeground(true)
+ }
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
new file mode 100644
index 0000000..837f089
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/service/SocketCommunicationService.kt
@@ -0,0 +1,62 @@
+package com.casic.app.safetreecontroller.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import com.casic.app.safetreecontroller.extensions.handleGasConcentration
+import com.casic.app.safetreecontroller.tcp.OnSocketConnectionListener
+import com.casic.app.safetreecontroller.tcp.TcpClient
+import com.casic.app.safetreecontroller.utils.CommandCreator
+
+class SocketCommunicationService : Service(), OnSocketConnectionListener {
+
+ private val kTag = "SocketService"
+
+ override fun onCreate() {
+ super.onCreate()
+ Log.d(kTag, "onCreate: SocketCommunicationService")
+ }
+
+ private var tcpClient: TcpClient? = null
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ tcpClient = TcpClient("192.168.161.200", 3000, this)
+ tcpClient?.start()
+ return START_STICKY
+ }
+
+ override fun onConnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110501)
+ tcpClient?.sendMessage(CommandCreator.createMethaneCommand())
+ }
+
+ override fun onDisconnected() {
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110502)
+ }
+
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ ForegroundRunningService.weakReferenceHandler?.sendEmptyMessage(2024110503)
+ }
+
+ override fun onMessageReceived(bytes: ByteArray?) {
+ Log.d(kTag, bytes.contentToString())
+ if (bytes == null) {
+ return
+ }
+ if (bytes.size == 7) {
+ val concentration = bytes.handleGasConcentration()
+ Log.d(kTag, "onMessageResponse: $concentration")
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ tcpClient?.stop()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
deleted file mode 100644
index 2c76c8c..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ConnectionState.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-enum class ConnectionState {
- /**
- * 正在连接
- * */
- CONNECTING,
-
- /**
- * 已连接
- * */
- CONNECTED,
-
- /**
- * 已断开连接
- * */
- DISCONNECTED,
-
- /**
- * 发生错误
- * */
- ERROR
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
deleted file mode 100644
index e7ebe2f..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/ISocketConnectionListener.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-interface ISocketConnectionListener {
-
- /**
- * Socket连接状态
- * */
- fun onServiceStatusConnectChanged(state: ConnectionState)
-
- /**
- * Socket数据
- * */
- fun onMessageResponse(bytes: ByteArray?)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
new file mode 100644
index 0000000..aeb3ac0
--- /dev/null
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/OnSocketConnectionListener.kt
@@ -0,0 +1,8 @@
+package com.casic.app.safetreecontroller.tcp
+
+interface OnSocketConnectionListener {
+ fun onConnected()
+ fun onDisconnected()
+ fun onError(t: Throwable)
+ fun onMessageReceived(bytes: ByteArray?)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
deleted file mode 100644
index 23b5cc0..0000000
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/SocketChannelHandler.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.casic.app.safetreecontroller.tcp
-
-import io.netty.channel.ChannelHandlerContext
-import io.netty.channel.SimpleChannelInboundHandler
-
-class SocketChannelHandler(private val listener: ISocketConnectionListener) :
- SimpleChannelInboundHandler() {
-
- override fun channelActive(ctx: ChannelHandlerContext) {
- super.channelActive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.CONNECTED)
- }
-
- override fun channelInactive(ctx: ChannelHandlerContext) {
- super.channelInactive(ctx)
- listener.onServiceStatusConnectChanged(ConnectionState.DISCONNECTED)
- }
-
- override fun channelRead0(ctx: ChannelHandlerContext, data: ByteArray?) {
- listener.onMessageResponse(data)
- }
-
- override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
- super.exceptionCaught(ctx, cause)
- cause.printStackTrace()
- ctx.close()
- listener.onServiceStatusConnectChanged(ConnectionState.ERROR)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt b/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
index 519b1ce..ef0b7e6 100644
--- a/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
+++ b/app/src/main/java/com/casic/app/safetreecontroller/tcp/TcpClient.kt
@@ -6,68 +6,125 @@
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
+import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
+import io.netty.channel.EventLoopGroup
+import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.codec.bytes.ByteArrayDecoder
import io.netty.handler.codec.bytes.ByteArrayEncoder
import io.netty.handler.timeout.IdleStateHandler
+import java.util.concurrent.TimeUnit
-class TcpClient(private val socketConnectionListener: ISocketConnectionListener) {
+
+class TcpClient(
+ private val host: String,
+ private val port: Int,
+ private val listener: OnSocketConnectionListener
+) {
private val kTag = "TcpClient"
- private var nioEventLoopGroup: NioEventLoopGroup? = null
+ private val reconnectDelay = 5L
+ private var bootstrap: Bootstrap = Bootstrap()
+ private var loopGroup: EventLoopGroup = NioEventLoopGroup()
private var channel: Channel? = null
+ private var isRunning = false
- fun startConnectTcpServer(hostname: String, port: Int) {
- nioEventLoopGroup = NioEventLoopGroup()
- val bootstrap = Bootstrap()
- bootstrap.group(nioEventLoopGroup) //设置的一系列连接参数操作等
+ fun start() {
+ if (isRunning) {
+ return
+ }
+ bootstrap.group(loopGroup)
.channel(NioSocketChannel::class.java)
.option(ChannelOption.TCP_NODELAY, true) //无阻塞
.option(ChannelOption.SO_KEEPALIVE, true) //长连接
.option(
- ChannelOption.RCVBUF_ALLOCATOR,
- AdaptiveRecvByteBufAllocator(5000, 5000, 8000)
- ) //接收缓冲区 最小值太小时数据接收不全
- .handler(object : ChannelInitializer() {
- override fun initChannel(channel: SocketChannel) {
- val pipeline = channel.pipeline()
- //参数1:代表读套接字超时的时间,没收到数据会触发读超时回调;
- //参数2:代表写套接字超时时间,没进行写会触发写超时回调;
- //参数3:将在未执行读取或写入时触发超时回调,0代表不处理;
- //读超时尽量设置大于写超时,代表多次写超时时写心跳包,多次写了心跳数据仍然读超时代表当前连接错误,即可断开连接重新连接
- pipeline.addLast(IdleStateHandler(60, 10, 0))
- pipeline.addLast(ByteArrayDecoder())
- pipeline.addLast(ByteArrayEncoder())
- pipeline.addLast(SocketChannelHandler(socketConnectionListener))
- }
- })
- try {
- //连接监听
- val channelFuture = bootstrap.connect(hostname, port)
- .addListener(object : ChannelFutureListener {
- override fun operationComplete(channelFuture: ChannelFuture) {
- if (channelFuture.isSuccess) {
- channel = channelFuture.channel()
+ ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator(5000, 5000, 8000)
+ )
+ .handler(SimpleChannelInitializer())
+ connect()
+ }
+
+ private inner class SimpleChannelInitializer : ChannelInitializer() {
+ override fun initChannel(ch: SocketChannel?) {
+ ch?.apply {
+ pipeline()
+ .addLast(IdleStateHandler(60, 10, 0))
+ .addLast(ByteArrayDecoder())
+ .addLast(ByteArrayEncoder())
+ .addLast(object : SimpleChannelInboundHandler() {
+ override fun channelActive(ctx: ChannelHandlerContext?) {
+ Log.d(kTag, "channelActive: ")
+ listener.onConnected()
}
- }
- }).sync()
- // 等待连接关闭
- channelFuture.channel().closeFuture().sync()
- } catch (e: Exception) {
- e.printStackTrace()
+
+ override fun channelInactive(ctx: ChannelHandlerContext?) {
+ Log.d(kTag, "channelInactive: ")
+ listener.onDisconnected()
+ reconnect()
+ }
+
+ override fun channelRead0(
+ ctx: ChannelHandlerContext?, msg: ByteArray?
+ ) {
+ listener.onMessageReceived(msg)
+ }
+
+ override fun exceptionCaught(
+ ctx: ChannelHandlerContext, cause: Throwable
+ ) {
+ Log.d(kTag, "exceptionCaught: ${cause.message}")
+ listener.onError(cause)
+ ctx.close()
+ }
+ })
+ }
}
}
- fun sendCommand(bytes: ByteArray) {
- channel?.writeAndFlush(bytes)
+ private fun connect() {
+ if (channel != null && channel!!.isActive) {
+ return
+ }
+
+ Thread {
+ try {
+ val channelFuture = bootstrap.connect(host, port)
+ .addListener(object : ChannelFutureListener {
+ override fun operationComplete(channelFuture: ChannelFuture) {
+ if (channelFuture.isSuccess) {
+ isRunning = true
+ channel = channelFuture.channel()
+ }
+ }
+ }).sync()
+ // 等待连接关闭
+ channelFuture.channel().closeFuture().sync()
+ } catch (e: Exception) {
+ Log.d(kTag, "connect: ${e.message}")
+ reconnect()
+ }
+ }.start()
}
- fun disconnect() {
- Log.d(kTag, "disconnect ===> 断开连接")
- nioEventLoopGroup?.shutdownGracefully()
+ private fun reconnect() {
+ loopGroup.schedule({ connect() }, reconnectDelay, TimeUnit.SECONDS)
+ Log.d(kTag, "Reconnecting: ")
+ }
+
+ fun stop() {
+ isRunning = false
+ channel?.close()
+ loopGroup.shutdownGracefully()
+ }
+
+ fun sendMessage(bytes: ByteArray) {
+ if (!isRunning) {
+ return
+ }
+ channel?.writeAndFlush(bytes)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/app/safetreecontroller/view/MainActivity.kt b/app/src/main/java/com/casic/app/safetreecontroller/view/MainActivity.kt
index 09c1168..d678e6e 100644
--- a/app/src/main/java/com/casic/app/safetreecontroller/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/app/safetreecontroller/view/MainActivity.kt
@@ -1,11 +1,9 @@
package com.casic.app.safetreecontroller.view
-import android.net.ConnectivityManager
-import android.net.Network
+import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Message
-import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
@@ -13,38 +11,31 @@
import com.casic.app.safetreecontroller.R
import com.casic.app.safetreecontroller.adapter.TabPageViewAdapter
import com.casic.app.safetreecontroller.databinding.ActivityMainBinding
-import com.casic.app.safetreecontroller.extensions.handleGasConcentration
import com.casic.app.safetreecontroller.extensions.initImmersionBar
import com.casic.app.safetreecontroller.fragments.BaseSettingsFragment
import com.casic.app.safetreecontroller.fragments.DeviceControllerFragment
import com.casic.app.safetreecontroller.fragments.MethaneMonitorFragment
import com.casic.app.safetreecontroller.fragments.VoiceSettingsFragment
-import com.casic.app.safetreecontroller.tcp.ConnectionState
-import com.casic.app.safetreecontroller.tcp.ISocketConnectionListener
-import com.casic.app.safetreecontroller.tcp.TcpClient
-import com.casic.app.safetreecontroller.utils.CommandCreator
+import com.casic.app.safetreecontroller.service.ForegroundRunningService
+import com.casic.app.safetreecontroller.service.SocketCommunicationService
import com.casic.app.safetreecontroller.utils.LocaleConstant
import com.casic.app.safetreecontroller.utils.VideoPlayerManager
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getScreenWidth
-import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.WeakReferenceHandler
import pub.devrel.easypermissions.EasyPermissions
class MainActivity : KotlinBaseActivity(), Handler.Callback,
- ISocketConnectionListener, EasyPermissions.PermissionCallbacks {
+ EasyPermissions.PermissionCallbacks {
companion object {
lateinit var weakReferenceHandler: WeakReferenceHandler
}
private val kTag = "MainActivity"
- private val context = this
private val fragmentPages by lazy { ArrayList() }
private val pageTitles = arrayOf("相机控制", "激光监测", "语音设置", "基础配置")
- private val tcpClient by lazy { TcpClient(this) }
- private val connectivityManager by lazy { getSystemService() }
private var clickTime: Long = 0
init {
@@ -67,6 +58,8 @@
LocaleConstant.PERMISSIONS_CODE, *LocaleConstant.USER_PERMISSIONS
)
+ startService(Intent(this, SocketCommunicationService::class.java))
+ startService(Intent(this, ForegroundRunningService::class.java))
weakReferenceHandler = WeakReferenceHandler(this)
binding.viewPager.adapter = TabPageViewAdapter(
@@ -93,24 +86,6 @@
}
- private val networkCallback = object : ConnectivityManager.NetworkCallback() {
- override fun onAvailable(network: Network) {
- super.onAvailable(network)
- if (connectivityManager?.bindProcessToNetwork(network) == true) {
- "安全树连接成功".show(context)
-
- /**
- * TODO 连接TCP板子,获取甲烷数据
- * */
- tcpClient.startConnectTcpServer("", 0)
- }
- }
-
- override fun onUnavailable() {
-
- }
- }
-
override fun initViewBinding(): ActivityMainBinding {
return ActivityMainBinding.inflate(layoutInflater)
}
@@ -123,40 +98,6 @@
binding.rootView.initImmersionBar(this, false, R.color.mainThemeColor)
}
- override fun onServiceStatusConnectChanged(state: ConnectionState) {
- when (state) {
- ConnectionState.CONNECTING -> {
- Log.d(kTag, "onServiceStatusConnectChanged: 连接中")
- }
-
- ConnectionState.CONNECTED -> {
- Log.d(kTag, "onServiceStatusConnectChanged: 已连接")
- tcpClient.sendCommand(CommandCreator.createMethaneCommand())
- }
-
- ConnectionState.DISCONNECTED -> {
- Log.d(kTag, "onServiceStatusConnectChanged: 断开连接,开始重连")
- tcpClient.startConnectTcpServer("", 0)
- }
-
- ConnectionState.ERROR -> {
- Log.d(kTag, "onServiceStatusConnectChanged: 连接出错,开始重连")
- tcpClient.startConnectTcpServer("", 0)
- }
- }
- }
-
- override fun onMessageResponse(bytes: ByteArray?) {
- Log.d(kTag, bytes.contentToString())
- if (bytes == null) {
- return
- }
- if (bytes.size == 7) {
- val concentration = bytes.handleGasConcentration()
- Log.d(kTag, "onMessageResponse: $concentration")
- }
- }
-
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array, grantResults: IntArray
) {
@@ -177,18 +118,11 @@
return super.onKeyDown(keyCode, event)
}
- override fun onDestroy() {
- super.onDestroy()
- tcpClient.disconnect()
- }
-
override fun onPermissionsGranted(requestCode: Int, perms: MutableList) {
}
override fun onPermissionsDenied(requestCode: Int, perms: MutableList) {
- perms.forEach {
- Log.d(kTag, "onPermissionsGranted: $it")
- }
+
}
}
\ No newline at end of file