Android应用从最近任务移除后无法接收短信并处理的问题求助
问题分析与解决方案
你的核心问题是应用从最近任务列表移除后,无法接收并处理短信,原因主要有两点:
- 静态注册的
BroadcastReceiver在Android 8+后台限制下,应用进程被杀死后无法被系统唤醒触发广播; - 你通过静态
mListener绑定MainActivity实例,当Activity销毁后mListener变为null,即使广播触发也会空指针,无法处理短信。
下面是可行的解决方案,基于前台服务+动态注册广播接收器实现,能保证应用在后台甚至最近任务被移除时仍能处理短信。
步骤1:创建前台服务处理短信逻辑
前台服务可以保持应用进程活跃,不受后台杀死限制,同时在服务内部动态注册短信广播,直接处理短信计算与存储。
package com.example.myapplication; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Build; import android.os.IBinder; import android.telephony.SmsMessage; import androidx.core.app.NotificationCompat; public class SmsProcessingService extends Service { private static final String CHANNEL_ID = "SmsServiceChannel"; private BroadcastReceiver smsReceiver; @Override public void onCreate() { super.onCreate(); // 创建通知渠道(Android 8+必填) createNotificationChannel(); // 启动前台服务,显示常驻通知 startForeground(1, buildNotification()); // 动态注册短信广播接收器 smsReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if ("android.provider.Telephony.SMS_RECEIVED".equals(intent.getAction())) { Object[] pdus = (Object[]) intent.getExtras().get("pdus"); for (Object pdu : pdus) { SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu); String message = smsMessage.getMessageBody(); // 执行你的计算逻辑并保存到SharedPreferences processAndSaveMessage(message); } } } }; IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); filter.setPriority(999); registerReceiver(smsReceiver, filter); } // 替换成你的实际计算逻辑 private void processAndSaveMessage(String message) { // 示例计算:假设提取数字求和 int total = 0; for (char c : message.toCharArray()) { if (Character.isDigit(c)) { total += Integer.parseInt(String.valueOf(c)); } } // 保存到SharedPreferences SharedPreferences sp = getSharedPreferences("spent", MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putString("spent", String.valueOf(total)); editor.apply(); } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( CHANNEL_ID, "短信处理服务", NotificationManager.IMPORTANCE_LOW ); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } } private Notification buildNotification() { return new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("短信处理中") .setContentText("应用正在后台处理短信") .setSmallIcon(R.mipmap.ic_launcher) .build(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); // 注销广播接收器,避免内存泄漏 if (smsReceiver != null) { unregisterReceiver(smsReceiver); } } }
步骤2:修改MainActivity启动前台服务
移除原来的Listener绑定逻辑,改为启动前台服务,并申请必要的权限。
package com.example.myapplication; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import android.Manifest; public class MainActivity extends AppCompatActivity { private TextView textView3; private TextView textView4; private static final int PERMISSION_REQUEST_CODE = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView3 = findViewById(R.id.textView10); textView4 = findViewById(R.id.textView7); // 读取SharedPreferences显示数据 SharedPreferences ts = getSharedPreferences("spent", MODE_PRIVATE); textView3.setText(ts.getString("spent", "0")); // 申请必要权限 requestRequiredPermissions(); // 启动前台服务 Intent serviceIntent = new Intent(this, SmsProcessingService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); } else { startService(serviceIntent); } textView4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SharedPreferences sp = getSharedPreferences("login-auth", MODE_PRIVATE); SharedPreferences.Editor spe = sp.edit(); spe.putBoolean("login-auth", false).apply(); Intent intent = new Intent(MainActivity.this, login.class); startActivity(intent); } }); } private void requestRequiredPermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { permissions = new String[]{ Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.POST_NOTIFICATIONS }; } else { permissions = new String[]{ Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS }; } boolean needRequest = false; for (String perm : permissions) { if (checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) { needRequest = true; break; } } if (needRequest) { requestPermissions(permissions, PERMISSION_REQUEST_CODE); } } } }
步骤3:修改AndroidManifest.xml
添加前台服务声明,移除原来的静态广播接收器(改用动态注册),补充必要权限。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" > <uses-permission android:name="android.permission.INTERNET"/> <uses-feature android:name="android.hardware.telephony" android:required="false" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <!-- 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Android 13+通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Material3.Light.NoActionBar" tools:targetApi="31" > <activity android:name=".register" android:theme="@style/Theme.Material3.Light.NoActionBar" android:parentActivityName=".login" android:exported="false" /> <activity android:name=".MainActivity" android:theme="@style/Theme.Material3.Light.NoActionBar" android:exported="false"/> <activity android:name=".login" android:theme="@style/Theme.Material3.Light.NoActionBar" android:exported="true" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 声明前台服务 --> <service android:name=".SmsProcessingService" android:foregroundServiceType="dataSync" android:exported="false"/> <!-- 移除静态注册的广播接收器,改用服务内动态注册 --> </application> </manifest>
额外注意事项
- 部分国产手机厂商有严格的后台管理机制,需要手动将应用加入后台白名单或自启动列表,否则前台服务可能被强制杀死;
- 前台服务必须显示常驻通知,这是系统强制要求,不能隐藏;
- 测试时请使用真实设备,模拟器的短信广播可能存在兼容性问题。
内容的提问来源于stack exchange,提问作者Matrix Gaming
相关产品推荐
相关产品推荐

