Android设备关机/重启时,应用能否检测状态并执行代码块(如发送邮件)?
Android设备关机前执行指定代码的实现方案
这个需求是可行的,Android系统通过广播机制提供了监听设备关机/重启事件的能力,以下是具体实现方案和注意事项:
1. 实现关机广播接收器
创建一个继承自BroadcastReceiver的类,在onReceive()方法中捕获关机或重启事件,并触发邮件发送逻辑:
public class ShutdownReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SHUTDOWN.equals(action) || Intent.ACTION_REBOOT.equals(action)) { // 启动后台任务处理邮件发送,避免阻塞广播接收器 startEmailService(context); } } private void startEmailService(Context context) { Intent serviceIntent = new Intent(context, ShutdownEmailService.class); // Android 8.0+ 需要启动前台服务 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(serviceIntent); } else { context.startService(serviceIntent); } } }
2. 实现邮件发送服务
由于广播接收器的生命周期极短(10秒内必须完成),邮件发送这种耗时操作需要放在服务中执行:
public class ShutdownEmailService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { // Android 8.0+ 需创建通知作为前台服务标识 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("shutdown_email", "Shutdown Email", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); Notification notification = new Notification.Builder(this, "shutdown_email") .setContentTitle("处理关机邮件") .setContentText("正在发送关机通知邮件") .setSmallIcon(R.drawable.ic_notification) .build(); startForeground(1, notification); } // 异步执行邮件发送 new Thread(() -> { try { // 这里实现SMTP邮件发送逻辑,需提前配置邮箱信息 sendEmail(); } catch (Exception e) { // 记录发送失败日志,可在下次开机时重试 Log.e("ShutdownEmail", "邮件发送失败: " + e.getMessage()); } finally { stopSelf(); } }).start(); return START_NOT_STICKY; } private void sendEmail() throws Exception { // 示例SMTP发送逻辑(需引入邮件库如JavaMail) Properties props = new Properties(); props.put("mail.smtp.host", "smtp.example.com"); props.put("mail.smtp.port", "587"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); Session session = Session.getInstance(props, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("your_email@example.com", "your_password"); } }); Message message = new MimeMessage(session); message.setFrom(new InternetAddress("your_email@example.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient@example.com")); message.setSubject("设备关机通知"); message.setText("您的Android设备已关机"); Transport.send(message); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
3. 配置清单文件与权限
在AndroidManifest.xml中添加必要权限、注册接收器和服务:
<!-- 网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 发送邮件权限 --> <uses-permission android:name="android.permission.SEND_EMAIL" /> <!-- Android 8.0+ 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application ...> <!-- 注册广播接收器 --> <receiver android:name=".ShutdownReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_SHUTDOWN" /> <action android:name="android.intent.action.REBOOT" /> </intent-filter> </receiver> <!-- 注册邮件服务 --> <service android:name=".ShutdownEmailService" /> </application>
关键注意事项
- 生命周期限制:广播接收器的
onReceive()方法必须在10秒内完成,绝对不能直接在其中执行耗时操作,必须通过后台服务处理。 - 系统版本兼容:Android 8.0及以上版本要求后台服务必须转为前台服务,否则会被系统强制停止。
- 可靠性问题:设备关机时系统会快速回收资源,邮件发送可能因网络中断或系统进程被杀死而失败,建议在本地缓存邮件任务,下次设备开机时重新尝试发送。
- 厂商定制限制:部分国产ROM可能对系统广播做了限制,需要在不同品牌设备上做兼容性测试。
内容的提问来源于stack exchange,提问作者Rizwan
相关产品推荐
相关产品推荐

