Android 10+无通知短信监听:杀进程/重启后组件保活咨询
针对你遇到的「应用被杀/重启后组件停止、Android 10+后台无通知运行、全版本短信监听」问题,直接给你可行的解决方案:
一、核心适配逻辑
Android各版本后台限制越来越严,加上厂商的电池优化策略,单纯靠静态广播+普通Service根本扛不住。得用「动态注册/辅助服务监听短信+开机自启动+厂商权限适配」的组合拳,才能满足需求。
二、全版本短信监听实现
1. Android 4.4~7.1
静态注册SMS_RECEIVED还能用,但为了统一后续版本逻辑,建议直接用动态注册:在Service或主Activity里注册广播接收器,进程存活时就能收到短信。
2. Android 8.0~9.0
静态隐式广播被系统限制,必须动态注册SMS_RECEIVED。但普通后台Service容易被杀死,要是不想显示前台通知,直接换**AccessibilityService(辅助服务)**更靠谱。
3. Android 10+
后台启动Service限制极严,普通Service存活时间短,前台Service又必须弹通知。这里给两个方案:
方案1:AccessibilityService(无通知首选)
辅助服务只要用户开启,就能长期在后台运行,无需显示通知,还能监听短信事件:
class SmsAccessibilityService : AccessibilityService() { override fun onAccessibilityEvent(event: AccessibilityEvent) { // 监听短信通知栏事件 if (event.eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) { val smsContent = event.text.joinToString("\n") Log.i("SmsAccess", "收到短信:$smsContent") // 调用你的postSms方法处理短信 postSms(smsContent, "", "", this) } // 若需更精准提取短信内容,可监听短信APP的界面变化(需适配不同厂商短信应用) } override fun onInterrupt() {} override fun onServiceConnected() { super.onServiceConnected() val serviceInfo = AccessibilityServiceInfo().apply { eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS } setServiceInfo(serviceInfo) } }
在Manifest中注册该服务:
<service android:name=".SmsAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:exported="false"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_config" /> </service>
在res/xml目录下创建accessibility_config.xml:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeNotificationStateChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagIncludeNotImportantViews" android:description="@string/accessibility_desc" android:notificationTimeout="100" />
在strings.xml添加辅助服务描述(需清晰告知用户用途,降低授权门槛):
<string name="accessibility_desc">用于后台监听短信,不会显示任何通知,仅在后台运行</string>
方案2:TelephonyManager监听(Android 12+专属)
Android 12+提供TelephonyManager.registerTelephonyCallbackAPI,可直接监听短信,比广播更稳定:
class SmsMonitorService : Service() { private lateinit var telephonyManager: TelephonyManager private lateinit var smsCallback: TelephonyCallback.SmsCallback override fun onCreate() { super.onCreate() telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager smsCallback = object : TelephonyCallback.SmsCallback() { override fun onSmsReceived(smsMessage: SmsMessage) { super.onSmsReceived(smsMessage) val msg = smsMessage.messageBody val number = smsMessage.displayOriginatingAddress val date = millisToDate(smsMessage.timestampMillis)!! Log.i("SmsMonitor", "短信内容:$msg,号码:$number") postSms(msg, number, date, this@SmsMonitorService) } } // 先检查权限 if (checkSelfPermission(Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED) { telephonyManager.registerTelephonyCallback(mainExecutor, smsCallback) } } override fun onBind(intent: Intent?): IBinder? = null override fun onDestroy() { super.onDestroy() telephonyManager.unregisterTelephonyCallback(smsCallback) } }
注意:该方案需保证Service存活,Android 10+若不用前台服务,进程很快会被回收。Android 14支持临时前台服务(无需通知),但旧版本仍需配合辅助服务或厂商权限才能稳定运行。
三、保活:杀后台/重启后继续运行
1. 开机自启动
静态注册BOOT_COMPLETED广播,设备重启后要么启动服务,要么引导用户开启辅助功能:
class BootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == "android.intent.action.QUICKBOOT_POWERON") { // 检查辅助服务是否开启 val isAccessEnabled = isAccessibilityServiceEnabled(context, SmsAccessibilityService::class.java) if (!isAccessEnabled) { // 跳转到辅助功能设置页 val settingsIntent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(settingsIntent) } else { // 启动监听服务(若使用Telephony方案) context.startService(Intent(context, SmsMonitorService::class.java)) } } } // 检查辅助服务是否开启的工具方法 private fun isAccessibilityServiceEnabled(context: Context, serviceClass: Class<out AccessibilityService>): Boolean { val accessibilityManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager val enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) for (serviceInfo in enabledServices) { if (serviceInfo.resolveInfo.serviceInfo.name == serviceClass.name) { return true } } return false } }
在Manifest中注册该广播:
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> </intent-filter> </receiver>
2. 厂商权限适配
小米、华为、OPPO、Vivo等品牌有自定义电池优化策略,必须引导用户开启以下权限才能保证后台存活:
- 自启动权限
- 忽略电池优化(后台活动权限)
- 后台弹出界面权限(部分机型)
以小米为例,跳转自启动设置页的代码:
fun openMiuiAutoStart(context: Context) { try { val intent = Intent() intent.component = ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity") context.startActivity(intent) } catch (e: Exception) { // 跳转应用详情页兜底 val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) intent.data = Uri.fromParts("package", context.packageName, null) context.startActivity(intent) } }
其他厂商的跳转逻辑可通过查询对应包名和类名实现。
3. 额外保活技巧
- 用WorkManager定期检查服务是否存活,未存活则重启。
- 在Service的
onDestroy方法中发送自定义广播尝试重启自身(Android 8+可能失效,但部分机型仍有效)。
四、现有代码优化
1. BroadcastReceiver拆分
你当前的RestarterReceiver同时处理短信和重启逻辑,职责混乱,建议拆分:
// 专门处理短信的动态广播接收器 class SmsReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action != "android.provider.Telephony.SMS_RECEIVED") return val bundle = intent.extras ?: return val pdus = bundle["pdus"] as? Array<Any> ?: return val msgs = pdus.map { SmsMessage.createFromPdu(it as ByteArray) } val fullMsg = msgs.joinToString("") { it.messageBody } val number = msgs.firstOrNull()?.displayOriginatingAddress ?: "" val date = msgs.firstOrNull()?.timestampMillis?.let { millisToDate(it) } ?: "" Log.i("SmsReceiver", "收到短信:$fullMsg,号码:$number,时间:$date") postSms(fullMsg, number, date, context) } }
2. Manifest优化
删除静态注册的SMS_RECEIVED(Android 8+无效),添加必要权限:
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <!-- 若使用前台服务,添加该权限:<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> -->
五、权限申请流程
- Android 6+动态申请
RECEIVE_SMS和READ_SMS权限。 - 引导用户开启辅助功能(使用Accessibility方案时)。
- 引导用户开启厂商的自启动、忽略电池优化权限。
内容的提问来源于stack exchange,提问作者Mohammad Zeeshan

