全部笔记All notes

Android广播机制与BroadcastReceiver完全指南

阅读 9m 54s9m 54s read

概述

广播(Broadcast)是Android系统中实现组件间通信的重要机制。通过广播,应用可以响应系统事件、接收其他应用的消息,或在应用内部传递信息。本指南深入介绍Android广播机制的工作原理、使用方法和最佳实践。

学习目标

  • 理解Android广播机制的工作原理
  • 掌握BroadcastReceiver的使用方法
  • 熟悉系统广播和自定义广播
  • 了解LocalBroadcastManager的优势
  • 学习WorkManager等现代替代方案
  • 掌握广播的安全性和性能优化

广播机制基础

什么是广播?

广播是Android四大组件之一,用于在不同组件之间进行通信。它基于观察者模式,允许应用程序对感兴趣的事件进行响应。

广播机制的工作流程

广播发送者 → Android系统(AMS) → 广播接收者
  1. 发送者:发送Intent形式的广播消息
  2. AMS:ActivityManagerService负责广播的分发
  3. 接收者:注册的BroadcastReceiver接收并处理广播

广播的特点

  • 解耦性:发送者和接收者不需要知道对方的存在
  • 异步性:广播的发送和接收是异步的
  • 多对多:一个广播可以被多个接收者接收
  • 系统级:可以接收系统级事件

BroadcastReceiver详解

创建BroadcastReceiver

// Java实现
public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    
    @Override
    public void onReceive(Context context, Intent intent) {
        // 处理接收到的广播
        String action = intent.getAction();
        Log.d(TAG, "Received broadcast: " + action);
        
        // 获取广播携带的数据
        if (intent.hasExtra("message")) {
            String message = intent.getStringExtra("message");
            Toast.makeText(context, "收到消息: " + message, 
                Toast.LENGTH_SHORT).show();
        }
        
        // 注意:onReceive运行在主线程,耗时操作需要开启新线程
        if (needLongRunningTask()) {
            // 使用GoAsync进行异步处理
            PendingResult pendingResult = goAsync();
            new Thread(() -> {
                try {
                    // 执行耗时操作
                    performLongRunningTask();
                } finally {
                    // 必须调用finish()结束
                    pendingResult.finish();
                }
            }).start();
        }
    }
    
    private boolean needLongRunningTask() {
        return false; // 示例返回值
    }
    
    private void performLongRunningTask() {
        // 执行耗时任务
    }
}
// Kotlin实现
class MyBroadcastReceiver : BroadcastReceiver() {
    companion object {
        private const val TAG = "MyBroadcastReceiver"
    }
    
    override fun onReceive(context: Context?, intent: Intent?) {
        // 处理接收到的广播
        val action = intent?.action
        Log.d(TAG, "Received broadcast: $action")
        
        // 获取广播携带的数据
        intent?.getStringExtra("message")?.let { message ->
            Toast.makeText(context, "收到消息: $message", 
                Toast.LENGTH_SHORT).show()
        }
        
        // 异步处理示例
        if (needLongRunningTask()) {
            val pendingResult = goAsync()
            Thread {
                try {
                    performLongRunningTask()
                } finally {
                    pendingResult.finish()
                }
            }.start()
        }
    }
    
    private fun needLongRunningTask() = false
    
    private fun performLongRunningTask() {
        // 执行耗时任务
    }
}

注册BroadcastReceiver

静态注册(清单文件注册)

<!-- AndroidManifest.xml -->
<receiver 
    android:name=".MyBroadcastReceiver"
    android:enabled="true"
    android:exported="false"> <!-- Android 12+ 必须指定exported -->
    <intent-filter>
        <action android:name="com.example.MY_CUSTOM_ACTION" />
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

⚠️ 注意:从Android 8.0(API 26)开始,静态注册的广播接收器有很多限制,大部分隐式广播不能通过静态注册接收。

动态注册(代码注册)

// Java实现
public class MainActivity extends AppCompatActivity {
    private MyBroadcastReceiver receiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 创建接收器实例
        receiver = new MyBroadcastReceiver();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        // 注册广播接收器
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.example.MY_CUSTOM_ACTION");
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        
        // Android 13+ 需要指定标志
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(receiver, filter, RECEIVER_NOT_EXPORTED);
        } else {
            registerReceiver(receiver, filter);
        }
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        // 取消注册,防止内存泄漏
        unregisterReceiver(receiver);
    }
}
// Kotlin实现
class MainActivity : AppCompatActivity() {
    private lateinit var receiver: MyBroadcastReceiver
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        receiver = MyBroadcastReceiver()
    }
    
    override fun onResume() {
        super.onResume()
        // 注册广播接收器
        val filter = IntentFilter().apply {
            addAction("com.example.MY_CUSTOM_ACTION")
            addAction(Intent.ACTION_BATTERY_CHANGED)
        }
        
        // Android 13+ 需要指定标志
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(receiver, filter, RECEIVER_NOT_EXPORTED)
        } else {
            registerReceiver(receiver, filter)
        }
    }
    
    override fun onPause() {
        super.onPause()
        // 取消注册
        unregisterReceiver(receiver)
    }
}

广播类型

标准广播(无序广播)

标准广播是完全异步执行的广播,所有接收者几乎同时接收到广播,没有先后顺序,效率较高。

发送标准广播

// Java实现
public void sendStandardBroadcast() {
    Intent intent = new Intent("com.example.STANDARD_BROADCAST");
    intent.putExtra("message", "这是一条标准广播");
    intent.putExtra("timestamp", System.currentTimeMillis());
    
    // Android 8.0+ 需要指定包名
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        intent.setPackage(getPackageName());
    }
    
    sendBroadcast(intent);
}
// Kotlin实现
fun sendStandardBroadcast() {
    val intent = Intent("com.example.STANDARD_BROADCAST").apply {
        putExtra("message", "这是一条标准广播")
        putExtra("timestamp", System.currentTimeMillis())
        
        // Android 8.0+ 需要指定包名
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            setPackage(packageName)
        }
    }
    
    sendBroadcast(intent)
}

有序广播

有序广播是同步执行的,接收者按优先级顺序接收广播,优先级高的接收者可以截断广播。

发送有序广播

// Java实现
public void sendOrderedBroadcast() {
    Intent intent = new Intent("com.example.ORDERED_BROADCAST");
    intent.putExtra("message", "这是一条有序广播");
    
    // 发送有序广播
    sendOrderedBroadcast(
        intent,
        null, // 权限
        new BroadcastReceiver() { // 最终接收者
            @Override
            public void onReceive(Context context, Intent intent) {
                // 这个接收者一定会收到广播,即使被拦截
                String result = getResultData();
                Log.d("FinalReceiver", "最终结果: " + result);
            }
        },
        null, // Handler
        Activity.RESULT_OK, // 初始code
        "初始数据", // 初始data
        null // 初始extras
    );
}
// Kotlin实现
fun sendOrderedBroadcast() {
    val intent = Intent("com.example.ORDERED_BROADCAST").apply {
        putExtra("message", "这是一条有序广播")
    }
    
    sendOrderedBroadcast(
        intent,
        null,
        object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                val result = resultData
                Log.d("FinalReceiver", "最终结果: $result")
            }
        },
        null,
        Activity.RESULT_OK,
        "初始数据",
        null
    )
}

设置优先级和拦截

// Java实现 - 高优先级接收者
public class HighPriorityReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取传递的数据
        String data = getResultData();
        Log.d("HighPriority", "收到数据: " + data);
        
        // 修改数据
        setResultData("数据被高优先级接收者修改");
        
        // 可选:拦截广播,后续接收者将收不到
        if (shouldIntercept()) {
            abortBroadcast();
        }
    }
    
    private boolean shouldIntercept() {
        // 根据业务逻辑决定是否拦截
        return false;
    }
}

// 注册时设置优先级
IntentFilter filter = new IntentFilter("com.example.ORDERED_BROADCAST");
filter.setPriority(1000); // 优先级范围:-1000 到 1000
registerReceiver(new HighPriorityReceiver(), filter);

本地广播

本地广播只在应用内部传播,更加高效和安全。

// Java实现 - 使用LocalBroadcastManager
public class LocalBroadcastExample {
    private LocalBroadcastManager localBroadcastManager;
    private BroadcastReceiver localReceiver;
    
    public void init(Context context) {
        localBroadcastManager = LocalBroadcastManager.getInstance(context);
        
        // 创建本地接收器
        localReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String message = intent.getStringExtra("message");
                Log.d("LocalBroadcast", "收到本地广播: " + message);
            }
        };
        
        // 注册本地接收器
        IntentFilter filter = new IntentFilter("com.example.LOCAL_ACTION");
        localBroadcastManager.registerReceiver(localReceiver, filter);
    }
    
    public void sendLocalBroadcast() {
        Intent intent = new Intent("com.example.LOCAL_ACTION");
        intent.putExtra("message", "本地广播消息");
        localBroadcastManager.sendBroadcast(intent);
    }
    
    public void cleanup() {
        localBroadcastManager.unregisterReceiver(localReceiver);
    }
}

粘性广播(已废弃)

⚠️ 注意:粘性广播(Sticky Broadcast)已在API 21中被废弃,不建议使用。

系统广播

常用系统广播

广播Action说明权限要求
ACTION_BOOT_COMPLETED系统启动完成RECEIVE_BOOT_COMPLETED
ACTION_BATTERY_CHANGED电池状态改变无(只能动态注册)
ACTION_SCREEN_ON/OFF屏幕开关无(只能动态注册)
ACTION_TIME_TICK时间每分钟改变无(只能动态注册)
ACTION_PACKAGE_ADDED应用安装无
ACTION_PACKAGE_REMOVED应用卸载无
CONNECTIVITY_ACTION网络状态改变ACCESS_NETWORK_STATE

监听系统广播示例

// Java实现 - 监听电池状态
public class BatteryReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
            // 获取电量信息
            int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
            int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
            float batteryPct = level * 100 / (float) scale;
            
            // 获取充电状态
            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                                status == BatteryManager.BATTERY_STATUS_FULL;
            
            // 获取充电方式
            int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
            boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
            boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
            
            Log.d("Battery", String.format(
                "电量: %.1f%%, 充电中: %b, USB充电: %b, AC充电: %b",
                batteryPct, isCharging, usbCharge, acCharge
            ));
        }
    }
}
// Kotlin实现 - 监听网络状态
class NetworkReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == ConnectivityManager.CONNECTIVITY_ACTION) {
            val cm = context?.getSystemService(Context.CONNECTIVITY_SERVICE) 
                as? ConnectivityManager
            
            val activeNetwork = cm?.activeNetworkInfo
            val isConnected = activeNetwork?.isConnected == true
            
            when (activeNetwork?.type) {
                ConnectivityManager.TYPE_WIFI -> {
                    Log.d("Network", "WiFi连接")
                }
                ConnectivityManager.TYPE_MOBILE -> {
                    Log.d("Network", "移动数据连接")
                }
                else -> {
                    Log.d("Network", "无网络连接")
                }
            }
        }
    }
}

自定义广播

定义广播Action

// Java实现 - 定义广播常量
public class BroadcastConstants {
    // 应用内广播
    public static final String ACTION_USER_LOGIN = "com.example.app.USER_LOGIN";
    public static final String ACTION_DATA_UPDATED = "com.example.app.DATA_UPDATED";
    public static final String ACTION_DOWNLOAD_COMPLETE = "com.example.app.DOWNLOAD_COMPLETE";
    
    // 广播Extra键
    public static final String EXTRA_USER_ID = "user_id";
    public static final String EXTRA_USER_NAME = "user_name";
    public static final String EXTRA_FILE_PATH = "file_path";
    public static final String EXTRA_PROGRESS = "progress";
}
// Kotlin实现 - 使用object定义常量
object BroadcastConstants {
    // 应用内广播
    const val ACTION_USER_LOGIN = "com.example.app.USER_LOGIN"
    const val ACTION_DATA_UPDATED = "com.example.app.DATA_UPDATED"
    const val ACTION_DOWNLOAD_COMPLETE = "com.example.app.DOWNLOAD_COMPLETE"
    
    // 广播Extra键
    const val EXTRA_USER_ID = "user_id"
    const val EXTRA_USER_NAME = "user_name"
    const val EXTRA_FILE_PATH = "file_path"
    const val EXTRA_PROGRESS = "progress"
}

完整的自定义广播示例

// Java实现 - 下载服务发送进度广播
public class DownloadService extends Service {
    private static final String TAG = "DownloadService";
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String url = intent.getStringExtra("url");
        startDownload(url);
        return START_STICKY;
    }
    
    private void startDownload(String url) {
        new Thread(() -> {
            try {
                // 模拟下载过程
                for (int progress = 0; progress <= 100; progress += 10) {
                    Thread.sleep(500);
                    
                    // 发送进度广播
                    Intent progressIntent = new Intent(BroadcastConstants.ACTION_DATA_UPDATED);
                    progressIntent.putExtra(BroadcastConstants.EXTRA_PROGRESS, progress);
                    sendBroadcast(progressIntent);
                    
                    Log.d(TAG, "Download progress: " + progress + "%");
                }
                
                // 发送完成广播
                Intent completeIntent = new Intent(BroadcastConstants.ACTION_DOWNLOAD_COMPLETE);
                completeIntent.putExtra(BroadcastConstants.EXTRA_FILE_PATH, "/sdcard/download/file.zip");
                sendBroadcast(completeIntent);
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

// 在Activity中接收广播
public class MainActivity extends AppCompatActivity {
    private ProgressBar progressBar;
    private TextView statusText;
    private BroadcastReceiver downloadReceiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        progressBar = findViewById(R.id.progressBar);
        statusText = findViewById(R.id.statusText);
        
        // 创建广播接收器
        downloadReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                
                if (BroadcastConstants.ACTION_DATA_UPDATED.equals(action)) {
                    int progress = intent.getIntExtra(BroadcastConstants.EXTRA_PROGRESS, 0);
                    progressBar.setProgress(progress);
                    statusText.setText("下载进度: " + progress + "%");
                    
                } else if (BroadcastConstants.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
                    String filePath = intent.getStringExtra(BroadcastConstants.EXTRA_FILE_PATH);
                    statusText.setText("下载完成: " + filePath);
                    Toast.makeText(context, "文件下载完成!", Toast.LENGTH_SHORT).show();
                }
            }
        };
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        // 注册接收器
        IntentFilter filter = new IntentFilter();
        filter.addAction(BroadcastConstants.ACTION_DATA_UPDATED);
        filter.addAction(BroadcastConstants.ACTION_DOWNLOAD_COMPLETE);
        registerReceiver(downloadReceiver, filter);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(downloadReceiver);
    }
    
    // 启动下载
    public void startDownload(View view) {
        Intent serviceIntent = new Intent(this, DownloadService.class);
        serviceIntent.putExtra("url", "https://example.com/file.zip");
        startService(serviceIntent);
    }
}

LocalBroadcastManager

为什么使用LocalBroadcastManager?

  1. 安全性:广播只在应用内部传递,其他应用无法接收
  2. 效率高:不需要进行IPC,直接在应用进程内传递
  3. 简单性:不需要担心权限问题

⚠️ 注意:LocalBroadcastManager已被标记为废弃,推荐使用LiveData或EventBus替代。

LocalBroadcastManager使用示例

// Java实现
public class LocalBroadcastActivity extends AppCompatActivity {
    private LocalBroadcastManager localBroadcastManager;
    private BroadcastReceiver messageReceiver;
    private TextView messageText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_local_broadcast);
        
        messageText = findViewById(R.id.messageText);
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        
        // 创建本地广播接收器
        messageReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String message = intent.getStringExtra("message");
                messageText.setText("收到消息: " + message);
            }
        };
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        // 注册本地广播接收器
        IntentFilter filter = new IntentFilter("LOCAL_MESSAGE");
        localBroadcastManager.registerReceiver(messageReceiver, filter);
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        // 取消注册
        localBroadcastManager.unregisterReceiver(messageReceiver);
    }
    
    // 发送本地广播
    public void sendLocalMessage(View view) {
        Intent intent = new Intent("LOCAL_MESSAGE");
        intent.putExtra("message", "Hello from Local Broadcast!");
        localBroadcastManager.sendBroadcast(intent);
    }
}

使用LiveData替代LocalBroadcastManager

// Kotlin实现 - 使用LiveData替代广播
object MessageBus {
    private val _messages = MutableLiveData<String>()
    val messages: LiveData<String> = _messages
    
    fun sendMessage(message: String) {
        _messages.postValue(message)
    }
}

// 在Activity中使用
class ModernActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_modern)
        
        // 观察消息
        MessageBus.messages.observe(this) { message ->
            messageTextView.text = "收到消息: $message"
        }
    }
    
    fun sendMessage(view: View) {
        MessageBus.sendMessage("Hello from LiveData!")
    }
}

权限与安全

广播权限

发送带权限的广播

// Java实现
public void sendPermissionBroadcast() {
    Intent intent = new Intent("com.example.SECURE_BROADCAST");
    intent.putExtra("data", "敏感数据");
    
    // 只有拥有特定权限的接收者才能接收
    sendBroadcast(intent, "com.example.permission.RECEIVE_SECURE_DATA");
}

接收带权限的广播

<!-- 在AndroidManifest.xml中声明权限 -->
<permission 
    android:name="com.example.permission.RECEIVE_SECURE_DATA"
    android:protectionLevel="signature" />

<uses-permission android:name="com.example.permission.RECEIVE_SECURE_DATA" />

<receiver 
    android:name=".SecureReceiver"
    android:permission="com.example.permission.RECEIVE_SECURE_DATA">
    <intent-filter>
        <action android:name="com.example.SECURE_BROADCAST" />
    </intent-filter>
</receiver>

安全最佳实践

  1. 使用显式Intent
// 不安全 - 隐式广播
Intent intent = new Intent("com.example.ACTION");
sendBroadcast(intent);

// 安全 - 显式广播
Intent intent = new Intent("com.example.ACTION");
intent.setPackage("com.example.targetapp");
sendBroadcast(intent);
  1. 验证广播来源
public class SecureReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 验证发送者包名
        String senderPackage = intent.getPackage();
        if (!"com.trusted.app".equals(senderPackage)) {
            Log.w("SecureReceiver", "未授权的广播发送者: " + senderPackage);
            return;
        }
        
        // 处理广播
        processSecureBroadcast(intent);
    }
}
  1. 使用签名级权限
<!-- 定义签名级权限,只有相同签名的应用才能使用 -->
<permission
    android:name="com.example.permission.INTERNAL_BROADCAST"
    android:protectionLevel="signature" />

WorkManager替代方案

为什么使用WorkManager?

WorkManager是Android Jetpack的一部分,用于处理可延迟的异步任务,是许多广播场景的更好替代方案。

WorkManager示例

// Kotlin实现 - 使用WorkManager处理周期性任务
class DataSyncWorker(context: Context, params: WorkerParameters) 
    : Worker(context, params) {
    
    override fun doWork(): Result {
        // 执行数据同步
        try {
            syncData()
            
            // 发送通知或更新UI
            val notification = createNotification("数据同步完成")
            NotificationManagerCompat.from(applicationContext)
                .notify(NOTIFICATION_ID, notification)
            
            return Result.success()
        } catch (e: Exception) {
            return Result.retry()
        }
    }
    
    private fun syncData() {
        // 实际的数据同步逻辑
    }
    
    private fun createNotification(message: String): Notification {
        // 创建通知
        return NotificationCompat.Builder(applicationContext, CHANNEL_ID)
            .setContentTitle("数据同步")
            .setContentText(message)
            .setSmallIcon(R.drawable.ic_sync)
            .build()
    }
    
    companion object {
        const val NOTIFICATION_ID = 1001
        const val CHANNEL_ID = "sync_channel"
    }
}

// 调度周期性任务
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 创建周期性工作请求
        val syncRequest = PeriodicWorkRequestBuilder<DataSyncWorker>(
            15, TimeUnit.MINUTES // 最小间隔15分钟
        ).setConstraints(
            Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .setRequiresBatteryNotLow(true)
                .build()
        ).build()
        
        // 调度工作
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            "data_sync",
            ExistingPeriodicWorkPolicy.KEEP,
            syncRequest
        )
    }
}

性能优化

1. 避免在onReceive中执行耗时操作

// 错误示例
public class BadReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // ❌ 不要在主线程执行耗时操作
        downloadFile(); // 耗时操作
        queryDatabase(); // 耗时操作
    }
}

// 正确示例
public class GoodReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // ✅ 使用goAsync()处理耗时操作
        PendingResult pendingResult = goAsync();
        
        new Thread(() -> {
            try {
                // 在后台线程执行耗时操作
                downloadFile();
                queryDatabase();
            } finally {
                // 必须调用finish()
                pendingResult.finish();
            }
        }).start();
    }
}

2. 及时取消注册

// 使用生命周期自动管理
public class LifecycleAwareActivity extends AppCompatActivity {
    private final BroadcastReceiver receiver = new MyReceiver();
    
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter("ACTION");
        registerReceiver(receiver, filter);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        // 确保取消注册,避免内存泄漏
        try {
            unregisterReceiver(receiver);
        } catch (IllegalArgumentException e) {
            // 接收器未注册
        }
    }
}

3. 使用合适的Context

// 如果广播接收器的生命周期与Activity相关
registerReceiver(receiver, filter); // 使用Activity的Context

// 如果需要在整个应用生命周期内接收
getApplicationContext().registerReceiver(receiver, filter);

最佳实践

1. 广播命名规范

// 使用包名作为前缀,避免冲突
public static final String ACTION_DATA_SYNC = "com.myapp.action.DATA_SYNC";
public static final String ACTION_USER_LOGIN = "com.myapp.action.USER_LOGIN";

2. 使用IntentFilter优化

// 添加多个Action
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);

// 设置数据类型
filter.addDataType("image/*");

// 设置数据Scheme
filter.addDataScheme("http");
filter.addDataScheme("https");

3. 处理Android版本差异

public class CompatBroadcastHelper {
    public static void registerReceiver(Context context, 
                                      BroadcastReceiver receiver, 
                                      IntentFilter filter,
                                      boolean exported) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            // Android 13及以上
            int flag = exported ? Context.RECEIVER_EXPORTED : 
                                Context.RECEIVER_NOT_EXPORTED;
            context.registerReceiver(receiver, filter, flag);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0及以上
            context.registerReceiver(receiver, filter);
        } else {
            // Android 8.0以下
            context.registerReceiver(receiver, filter);
        }
    }
}

4. 实现广播队列

// Kotlin实现 - 广播队列管理
class BroadcastQueue {
    private val queue = LinkedBlockingQueue<Intent>()
    private val handler = Handler(Looper.getMainLooper())
    
    fun enqueue(intent: Intent) {
        queue.offer(intent)
        processQueue()
    }
    
    private fun processQueue() {
        handler.post {
            queue.poll()?.let { intent ->
                // 处理广播
                processBroadcast(intent)
                
                // 延迟处理下一个
                handler.postDelayed({ processQueue() }, 100)
            }
        }
    }
    
    private fun processBroadcast(intent: Intent) {
        // 实际处理逻辑
    }
}

调试技巧

1. 使用ADB调试广播

# 发送自定义广播
adb shell am broadcast -a com.example.MY_ACTION 

# 发送带数据的广播
adb shell am broadcast -a com.example.MY_ACTION \
  --es message "Hello World" \
  --ei count 10

# 发送系统广播(需要root)
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

# 查看广播接收器
adb shell dumpsys activity broadcasts

2. 日志调试

public class DebugReceiver extends BroadcastReceiver {
    private static final String TAG = "DebugReceiver";
    
    @Override
    public void onReceive(Context context, Intent intent) {
        // 打印完整的Intent信息
        Log.d(TAG, "Action: " + intent.getAction());
        Log.d(TAG, "Data: " + intent.getDataString());
        Log.d(TAG, "Categories: " + intent.getCategories());
        
        // 打印所有Extra
        Bundle extras = intent.getExtras();
        if (extras != null) {
            for (String key : extras.keySet()) {
                Log.d(TAG, "Extra[" + key + "]: " + extras.get(key));
            }
        }
        
        // 打印调用栈
        Log.d(TAG, "Stack trace:", new Exception());
    }
}

3. 监控广播性能

public class PerformanceMonitorReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        long startTime = SystemClock.elapsedRealtime();
        
        try {
            // 实际处理逻辑
            processBroadcast(context, intent);
        } finally {
            long duration = SystemClock.elapsedRealtime() - startTime;
            if (duration > 1000) { // 超过1秒
                Log.w("Performance", "Broadcast处理耗时: " + duration + "ms");
            }
        }
    }
}

常见问题

1. 广播接收不到

问题原因:

  • Android 8.0+限制了隐式广播
  • 没有正确设置exported属性
  • 权限问题

解决方案:

// 使用显式Intent
Intent intent = new Intent("ACTION");
intent.setPackage(getPackageName());
sendBroadcast(intent);

// 正确设置exported
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    registerReceiver(receiver, filter, RECEIVER_NOT_EXPORTED);
}

2. ANR(应用无响应)

问题原因:在onReceive中执行耗时操作

解决方案:

@Override
public void onReceive(Context context, Intent intent) {
    // 启动Service处理耗时操作
    Intent serviceIntent = new Intent(context, ProcessService.class);
    serviceIntent.putExtras(intent.getExtras());
    context.startService(serviceIntent);
}

3. 内存泄漏

问题原因:未取消注册BroadcastReceiver

解决方案:

// 使用try-catch避免重复取消注册导致的异常
@Override
protected void onDestroy() {
    super.onDestroy();
    try {
        unregisterReceiver(receiver);
    } catch (Exception e) {
        // 已经取消注册
    }
}

4. 有序广播被截断

问题原因:高优先级接收器调用了abortBroadcast()

解决方案:

// 发送时指定最终接收器
sendOrderedBroadcast(intent, null, finalReceiver, null, 0, null, null);

相关文章

总结

Android广播机制是实现组件间通信的重要方式,但随着Android版本的更新,其使用方式和限制也在不断变化。开发者需要:

  1. 理解不同类型广播的特点和使用场景
  2. 注意Android版本差异,特别是8.0+的限制
  3. 重视安全性,使用权限和签名保护敏感广播
  4. 考虑使用现代替代方案如LiveData、EventBus、WorkManager
  5. 避免在广播接收器中执行耗时操作
  6. 及时取消注册,防止内存泄漏

通过合理使用广播机制,可以构建松耦合、响应式的Android应用。