diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/OnlineMsgServer.iml b/.idea/OnlineMsgServer.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/OnlineMsgServer.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml new file mode 100644 index 0000000..23267a6 --- /dev/null +++ b/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1490 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..4b151ab --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..7801fe1 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android-client/app/src/main/java/com/onlinemsg/client/MainActivity.kt b/android-client/app/src/main/java/com/onlinemsg/client/MainActivity.kt index defba49..a07bba6 100644 --- a/android-client/app/src/main/java/com/onlinemsg/client/MainActivity.kt +++ b/android-client/app/src/main/java/com/onlinemsg/client/MainActivity.kt @@ -9,9 +9,11 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import com.onlinemsg.client.service.ChatForegroundService import com.onlinemsg.client.ui.OnlineMsgApp class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requestNotificationPermissionIfNeeded() @@ -21,21 +23,53 @@ class MainActivity : ComponentActivity() { } } + private val PERMISSION_REQUEST_NOTIFICATIONS = 1001 + private fun requestNotificationPermissionIfNeeded() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return val granted = ContextCompat.checkSelfPermission( this, Manifest.permission.POST_NOTIFICATIONS ) == PackageManager.PERMISSION_GRANTED - if (granted) return - ActivityCompat.requestPermissions( - this, - arrayOf(Manifest.permission.POST_NOTIFICATIONS), - REQUEST_NOTIFICATION_PERMISSION - ) + if (granted) { + // 已有权限 + startForegroundServiceIfNeeded() + } else { + // 请求权限 + ActivityCompat.requestPermissions( + this, + arrayOf(Manifest.permission.POST_NOTIFICATIONS), + REQUEST_NOTIFICATION_PERMISSION + ) + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + when (requestCode) { + REQUEST_NOTIFICATION_PERMISSION -> { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + /* 授予权限的处理 */ + startForegroundServiceIfNeeded() + } else { + /* 拒绝权限的处理 */ + } + } + } + } + + /** + * 根据业务逻辑决定何时启动前台服务(@emilia-t) + */ + private fun startForegroundServiceIfNeeded() { + ChatForegroundService.start(this) } private companion object { const val REQUEST_NOTIFICATION_PERMISSION = 1002 } -} +} \ No newline at end of file diff --git a/android-client/app/src/main/java/com/onlinemsg/client/service/ChatForegroundService.kt b/android-client/app/src/main/java/com/onlinemsg/client/service/ChatForegroundService.kt index 0ebaa12..8566d22 100644 --- a/android-client/app/src/main/java/com/onlinemsg/client/service/ChatForegroundService.kt +++ b/android-client/app/src/main/java/com/onlinemsg/client/service/ChatForegroundService.kt @@ -21,6 +21,10 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +import android.Manifest +import android.content.pm.PackageManager +import android.util.Log +import android.annotation.SuppressLint class ChatForegroundService : Service() { @@ -62,6 +66,18 @@ class ChatForegroundService : Service() { override fun onBind(intent: Intent?): IBinder? = null + /** + * 权限检查函数(@emilia-t) + */ + private fun hasNotificationPermission(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + true // 低于 Android 13 不需要权限 + } + } + + @SuppressLint("MissingPermission") private fun observeStatusAndRefreshNotification() { if (statusJob != null) return statusJob = serviceScope.launch { @@ -69,10 +85,15 @@ class ChatForegroundService : Service() { .map { it.status to it.statusHint } .distinctUntilChanged() .collect { (status, hint) -> - NotificationManagerCompat.from(this@ChatForegroundService).notify( - FOREGROUND_NOTIFICATION_ID, - buildForegroundNotification(status, hint) - ) + /* 检查是否有通知权限(@emilia-t) */ + if (hasNotificationPermission()) { + NotificationManagerCompat.from(this@ChatForegroundService).notify( + FOREGROUND_NOTIFICATION_ID, + buildForegroundNotification(status, hint) + ) + } else { + Log.d("ChatForegroundService", "通知权限缺失,跳过前台通知更新") + } if (status == ConnectionStatus.IDLE && !ChatSessionManager.shouldForegroundServiceRun()) { stopForeground(STOP_FOREGROUND_REMOVE) stopSelf()