Anonymous
Слушайте SMS -сообщения, пока приложение Kotlin находится в заднем плане
Сообщение
Anonymous » 15 авг 2025, 14:58
Итак, я попытался написать код, который будет получать SMS -сообщения, даже если приложение находится в фоновом режиме (оно закрыто), но оно печатает только если приложение находится в активном состоянии.
Основная проблема заключается в том, что SMS -сообщения просто не получаются, когда приложение находится в фоновом режиме < /p>
Вот код для Smsservice: < /p>
.
Код: Выделить всё
package com.sms.push
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.graphics.Color
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.PRIORITY_MAX
import androidx.core.app.ServiceCompat
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
class SmsService : Service() {
private val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
Log.e("SmsService", "Coroutine exception: ${throwable.message}")
}
private val workerScope = CoroutineScope(Dispatchers.Default + exceptionHandler)
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
launchNotification(intent)
return START_REDELIVER_INTENT
}
private fun launchNotification(intent: Intent?) {
val channelId = createNotificationChannel()
val notificationBuilder = NotificationCompat.Builder(this, channelId)
val notification = notificationBuilder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher)
.setPriority(PRIORITY_MAX).setContentText(intent?.getStringExtra("text"))
.setCategory(Notification.CATEGORY_SERVICE).build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ServiceCompat.startForeground(
this,
notificationId,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
)
} else {
startForeground(notificationId, notification)
}
}
private fun createNotificationChannel(): String {
val channelId = "sms_service"
val channelName = "sms_service"
val chan = NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_HIGH
)
chan.lightColor = Color.BLUE
chan.importance = NotificationManager.IMPORTANCE_NONE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return channelId
}
override fun onDestroy() {
workerScope.cancel()
super.onDestroy()
}
}
< /code>
код для SMS -приемник: < /p>
package com.sms.push
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.provider.Telephony
import com.sms.push.models.ValidSmsModel
class SmsReceiver : BroadcastReceiver() {
private lateinit var context: Context
override fun onReceive(context: Context, intent: Intent) {
this.context = context
val message = extractMessageFromIntent(intent)
message?.let {
App.onNewSms(message)
}
}
private fun extractMessageFromIntent(intent: Intent): ValidSmsModel? {
val smsMessages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
return if (smsMessages.isNotEmpty()) {
val sender = smsMessages.first().originatingAddress ?: ""
val sentTime = smsMessages.first().timestampMillis / 1000
val allSms = smsMessages.joinToString(separator = "") { it.messageBody }
ValidSmsModel(sender, sentTime, allSms, ReadType.Sms)
} else {
null
}
}
}
< /code>
и для уведомления Listenerservice: < /p>
пакет com.sms.push < /p>
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import com.sms.push.models.ValidSmsModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
class NotificationListenerService : NotificationListenerService() {
private val exception = CoroutineExceptionHandler { coroutineContext, throwable -> }
private val coroutineScope = CoroutineScope(Dispatchers.IO + exception + SupervisorJob())
override fun onNotificationPosted(sbn: StatusBarNotification?, rankingMap: RankingMap?) {
super.onNotificationPosted(sbn, rankingMap)
}
override fun onListenerConnected() {
super.onListenerConnected()
}
override fun onNotificationPosted(sbn: StatusBarNotification?) {
sbn?.let { statusbarNotif ->
sendPushBroadcast(statusbarNotif)
}
super.onNotificationPosted(sbn)
}
private fun sendPushBroadcast(sbn: StatusBarNotification) {
val extras = sbn.notification.extras
val title = extras.getString("android.title").toString()
val text = extras.getCharSequence("android.text").toString()
val packageName = sbn.packageName
App.onNewSms(
ValidSmsModel(
sender = packageName.toString(),
sentTime = System.currentTimeMillis(),
allSms = "$title $text",
readType = ReadType.Notification
)
)
}
override fun onDestroy() {
super.onDestroy()
coroutineScope.cancel()
}
}
< /code>
Android Manifest: < /p>
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="This service listens sms" />
Я слышал, что вещательный приемник должен работать, даже если приложение не активно (не полный экран)
Подробнее здесь:
https://stackoverflow.com/questions/797 ... background
1755259128
Anonymous
Итак, я попытался написать код, который будет получать SMS -сообщения, даже если приложение находится в фоновом режиме (оно закрыто), но оно печатает только если приложение находится в активном состоянии. Основная проблема заключается в том, что SMS -сообщения просто не получаются, когда приложение находится в фоновом режиме < /p> Вот код для Smsservice: < /p> .[code]package com.sms.push import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.Service import android.content.Context import android.content.Intent import android.content.pm.ServiceInfo import android.graphics.Color import android.os.Build import android.os.IBinder import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat.PRIORITY_MAX import androidx.core.app.ServiceCompat import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel class SmsService : Service() { private val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable -> Log.e("SmsService", "Coroutine exception: ${throwable.message}") } private val workerScope = CoroutineScope(Dispatchers.Default + exceptionHandler) override fun onBind(intent: Intent?): IBinder? { return null } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { launchNotification(intent) return START_REDELIVER_INTENT } private fun launchNotification(intent: Intent?) { val channelId = createNotificationChannel() val notificationBuilder = NotificationCompat.Builder(this, channelId) val notification = notificationBuilder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher) .setPriority(PRIORITY_MAX).setContentText(intent?.getStringExtra("text")) .setCategory(Notification.CATEGORY_SERVICE).build() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { ServiceCompat.startForeground( this, notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE ) } else { startForeground(notificationId, notification) } } private fun createNotificationChannel(): String { val channelId = "sms_service" val channelName = "sms_service" val chan = NotificationChannel( channelId, channelName, NotificationManager.IMPORTANCE_HIGH ) chan.lightColor = Color.BLUE chan.importance = NotificationManager.IMPORTANCE_NONE chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager service.createNotificationChannel(chan) return channelId } override fun onDestroy() { workerScope.cancel() super.onDestroy() } } < /code> код для SMS -приемник: < /p> package com.sms.push import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.provider.Telephony import com.sms.push.models.ValidSmsModel class SmsReceiver : BroadcastReceiver() { private lateinit var context: Context override fun onReceive(context: Context, intent: Intent) { this.context = context val message = extractMessageFromIntent(intent) message?.let { App.onNewSms(message) } } private fun extractMessageFromIntent(intent: Intent): ValidSmsModel? { val smsMessages = Telephony.Sms.Intents.getMessagesFromIntent(intent) return if (smsMessages.isNotEmpty()) { val sender = smsMessages.first().originatingAddress ?: "" val sentTime = smsMessages.first().timestampMillis / 1000 val allSms = smsMessages.joinToString(separator = "") { it.messageBody } ValidSmsModel(sender, sentTime, allSms, ReadType.Sms) } else { null } } } < /code> и для уведомления Listenerservice: < /p> пакет com.sms.push < /p> import android.service.notification.NotificationListenerService import android.service.notification.StatusBarNotification import com.sms.push.models.ValidSmsModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel class NotificationListenerService : NotificationListenerService() { private val exception = CoroutineExceptionHandler { coroutineContext, throwable -> } private val coroutineScope = CoroutineScope(Dispatchers.IO + exception + SupervisorJob()) override fun onNotificationPosted(sbn: StatusBarNotification?, rankingMap: RankingMap?) { super.onNotificationPosted(sbn, rankingMap) } override fun onListenerConnected() { super.onListenerConnected() } override fun onNotificationPosted(sbn: StatusBarNotification?) { sbn?.let { statusbarNotif -> sendPushBroadcast(statusbarNotif) } super.onNotificationPosted(sbn) } private fun sendPushBroadcast(sbn: StatusBarNotification) { val extras = sbn.notification.extras val title = extras.getString("android.title").toString() val text = extras.getCharSequence("android.text").toString() val packageName = sbn.packageName App.onNewSms( ValidSmsModel( sender = packageName.toString(), sentTime = System.currentTimeMillis(), allSms = "$title $text", readType = ReadType.Notification ) ) } override fun onDestroy() { super.onDestroy() coroutineScope.cancel() } } < /code> Android Manifest: < /p> android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="This service listens sms" /> [/code] Я слышал, что вещательный приемник должен работать, даже если приложение не активно (не полный экран) Подробнее здесь: [url]https://stackoverflow.com/questions/79736393/listen-to-sms-messages-while-the-kotlin-app-is-in-the-background[/url]