You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Android短信应用在关闭或销毁时接收短信?

解决Android短信应用关闭后无法接收短信的问题

看起来你遇到的是Android 8.0+系统对广播接收器的限制导致的问题——静态注册的广播接收器在应用处于停止状态(被关闭后)无法接收隐式广播,这是系统为了优化电池和性能引入的规则。你的SmsBroadcastReceiver是静态注册在Manifest里的,所以一旦应用被关闭,系统就不会再把短信/彩信广播分发给它了。

下面是具体的解决方案,一步步来:

核心思路:用前台服务+动态注册广播接收器

前台服务的优先级远高于普通后台服务,只要前台服务在运行,应用就不会被系统标记为"停止状态"。我们可以在前台服务里动态注册广播接收器,这样即使应用界面被关闭,服务仍然会持续监听短信广播。

1. 补充Manifest权限与服务注册

首先更新你的Manifest,添加必要的权限和前台服务的注册:

<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 接收WAP Push(彩信)的权限 -->
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<!-- 如果需要接收普通短信,加上这个 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<!-- Android 13+ 需要通知权限才能显示前台服务通知 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<!-- 注册前台服务 -->
<service
    android:name=".SmsForegroundService"
    android:foregroundServiceType="dataSync" /> <!-- dataSync适合数据同步/监听场景 -->

<!-- 可以保留原来的静态接收器,但它只在应用运行时生效,主要依赖动态注册 -->
<receiver android:name=".SmsBroadcastReceiver" 
          android:enabled="true" 
          android:exported="true" 
          android:permission="android.permission.BROADCAST_WAP_PUSH">
    <intent-filter android:priority="999" >
        <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
        <!-- 普通短信的话加上这个 -->
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

2. 创建前台服务类

新建一个SmsForegroundService类,在里面动态注册广播接收器,并启动前台服务:

class SmsForegroundService : Service() {
    private lateinit var smsReceiver: SmsBroadcastReceiver

    override fun onCreate() {
        super.onCreate()
        // 初始化并注册广播接收器
        smsReceiver = SmsBroadcastReceiver()
        val intentFilter = IntentFilter().apply {
            addAction("android.provider.Telephony.WAP_PUSH_DELIVER")
            addAction("android.provider.Telephony.SMS_RECEIVED") // 可选,普通短信监听
            priority = 999
        }
        registerReceiver(smsReceiver, intentFilter)

        // 创建前台服务通知(必须,否则系统会杀服务)
        val notificationChannelId = "SMS_LISTENER_CHANNEL"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                notificationChannelId,
                "短信监听通道",
                NotificationManager.IMPORTANCE_LOW // 低优先级,避免打扰用户
            )
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }

        val notification = NotificationCompat.Builder(this, notificationChannelId)
            .setContentTitle("短信服务运行中")
            .setContentText("应用正在后台接收短信/彩信")
            .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .build()

        // 启动前台服务
        startForeground(1001, notification)
    }

    override fun onDestroy() {
        super.onDestroy()
        // 注销接收器,避免内存泄漏
        unregisterReceiver(smsReceiver)
    }

    override fun onBind(intent: Intent): IBinder? {
        return null // 不需要绑定服务,返回null即可
    }
}

3. 启动前台服务

在应用启动时(比如MainActivity的onCreate方法)启动这个前台服务,确保服务随应用启动而运行:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 检查权限并启动前台服务
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val permissions = arrayOf(
            Manifest.permission.RECEIVE_WAP_PUSH,
            Manifest.permission.RECEIVE_SMS,
            Manifest.permission.POST_NOTIFICATIONS
        )
        if (checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED ||
            checkSelfPermission(permissions[1]) != PackageManager.PERMISSION_GRANTED ||
            (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && checkSelfPermission(permissions[2]) != PackageManager.PERMISSION_GRANTED)
        ) {
            requestPermissions(permissions, 100)
        } else {
            startForegroundService()
        }
    } else {
        startForegroundService()
    }
}

private fun startForegroundService() {
    val intent = Intent(this, SmsForegroundService::class.java)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(intent)
    } else {
        startService(intent)
    }
}

// 处理权限申请结果
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 100 && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
        startForegroundService()
    }
}

关键注意点

  • 前台服务必须显示通知:从Android 8.0开始,前台服务必须绑定一个可见的通知,你可以把通知设置为低优先级,减少对用户的打扰。
  • 动态权限申请:RECEIVE_WAP_PUSH、RECEIVE_SMS和POST_NOTIFICATIONS都是危险权限,必须在运行时向用户申请,不能只依赖Manifest声明。
  • 避免内存泄漏:在服务销毁时一定要注销广播接收器,否则会导致内存泄漏。

这样改造后,即使用户关闭了应用的界面,前台服务仍然会在后台运行,广播接收器也能持续接收到短信/彩信广播了。

内容的提问来源于stack exchange,提问作者user8515823

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:58:03