自定义广播的使用

import static android.content.ContentValues.TAG;

//在主线程里面处理消息并更新UI界面
public class MyBroadcastReceiver extends BroadcastReceiver {
    String name1;
    @Override
    public void onReceive( Context context, Intent intent) {
        String a =intent.getStringExtra ( "name" );
        Toast.makeText(context,a,Toast.LENGTH_SHORT).show();
        Log.d(TAG,"0000000");
        name1=a;
    }

}

定义BoardcastReceiver 并且仿写 OnRreceive,把想执行的方法写进去。

 MyBroadcastReceiver broadcastReceiver =new MyBroadcastReceiver ();
    IntentFilter intentFilter = new IntentFilter ();
    intentFilter.addAction ( "mybroadcast" );
    registerReceiver ( broadcastReceiver, intentFilter );

在主页要声明Broadcast Receiver,说明需要执行那些action

  Intent intent = new Intent();
                    intent.setAction("mybroadcast");
                    intent.putExtra ( "name" ,f);
                    sendBroadcast(intent);

使用intent 把broadcast 发出去
可以用extra 带一些信息走

 <receiver android:name=".MyBroadcastReceiver">
            <intent-filter>

                <action android:name="mybroadcast" />
            </intent-filter>
        </receiver>

在 manifest进行声明要进行广播的名字与自定义广播的类名。

<think>我们正在讨论Android自定义广播使用实例,特别是考虑到Android13到15的版本适配问题。以下是一个完整的自定义广播使用示例,包含了动态注册、静态注册以及适配新版本的要点。###一、自定义广播使用实例(含版本适配)####1.动态注册广播接收器(带版本适配)```kotlin//定义自定义广播ActionconstvalINTERNAL_BROADCAST_ACTION="com.example.app.INTERNAL_ACTION"classMainActivity:AppCompatActivity(){privatelateinitvarreceiver:BroadcastReceiveroverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//初始化广播接收器receiver=object:BroadcastReceiver(){overridefunonReceive(context:Context,intent:Intent){if(intent.action==INTERNAL_BROADCAST_ACTION){valdata=intent.getStringExtra("data")Toast.makeText(context,"收到广播:$data",Toast.LENGTH_SHORT).show()}}}//注册广播Android13+适配)valfilter=IntentFilter(INTERNAL_BROADCAST_ACTION)if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU){registerReceiver(receiver,filter,Context.RECEIVER_NOT_EXPORTED)//应用内广播}else{registerReceiver(receiver,filter)}//发送广播的按钮findViewById<Button>(R.id.btn_send).setOnClickListener{sendInternalBroadcast()}}overridefunonDestroy(){super.onDestroy()unregisterReceiver(receiver)//解注册}//发送应用内广播(适配后台限制)privatefunsendInternalBroadcast(){valintent=Intent(INTERNAL_BROADCAST_ACTION).apply{putExtra("data","来自MainActivity的消息")//Android8.0+需要设置包名避免后台限制setPackage(packageName)}sendBroadcast(intent)}}```####2.静态注册广播接收器(AndroidManifest.xml配置)```xml<application...><!--静态注册的广播接收器(必须声明exported属性)--><receiverandroid:name=".StaticReceiver"android:exported="false"><!--应用内广播设为false--><intent-filter><actionandroid:name="com.example.app.STATIC_ACTION"/></intent-filter></receiver></application>``````kotlinclassStaticReceiver:BroadcastReceiver(){overridefunonReceive(context:Context,intent:Intent){if(intent.action=="com.example.app.STATIC_ACTION"){//处理唤醒逻辑(注意后台限制)valdata=intent.getStringExtra("wakeup_data")Log.d("StaticReceiver","唤醒应用:$data")}}}```####3.发送广播给静态接收器(带版本适配)```kotlin//发送给静态注册的接收器funsendToStaticReceiver(context:Context){valintent=Intent("com.example.app.STATIC_ACTION").apply{putExtra("wakeup_data","系统事件触发")//适配Android12+:需声明PendingIntent的可变性if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){addFlags(Intent.FLAG_RECEIVER_FROM_SHELL)}//设置包名避免后台限制(Android8.0+)setPackage(context.packageName)}context.sendBroadcast(intent)}```###二、关键适配要点1.**动态注册导出标志**(Android13+)-使用`Context.RECEIVER_NOT_EXPORTED`标记应用内广播[^1][^3]-低于Android13的设备保持原注册方式2.**静态注册exported属性**(Android8.0+强化,14+强制)-所有`<receiver>`必须显式声明`android:exported`-应用内广播设为`false`[^1]3.**后台广播限制规避**(Android8.0+)-发送广播时调用`intent.setPackage(context.packageName)`-使广播变为显式广播,绕过后台限制[^4]4.**PendingIntent可变性**(Android12+)-如果使用PendingIntent发送广播,需添加`FLAG_MUTABLE`或`FLAG_IMMUTABLE`[^3]###三、替代方案推荐对于纯粹应用内通信,建议考虑替代方案:```mermaidgraphTDA[组件通信]-->B[广播]A-->C[LocalBroadcastManager]A-->D[EventBus/RxJava]A-->E[ViewModel+LiveData]```-**LocalBroadcastManager**(已废弃)→迁移到`LiveData`或`Flow`-**跨进程通信**→使用`ContentProvider`或`AIDL`###四、常见问题解决####❌静态接收器收不到广播-检查`android:exported`是否声明-确认发送广播时设置了包名`setPackage()`-Android10+需添加`<queries>`声明(跨应用时)[^4]####❌动态注册接收器崩溃(Android13+)```logjava.lang.SecurityException:Notallowedtoregisterbroadcastreceiver...```-动态注册缺少`RECEIVER_NOT_EXPORTED`标志[^3]####❌后台无法接收(Android9+)```logBackgroundexecutionnotallowed:receivingIntent...```-改用`JobScheduler`或`WorkManager`替代后台触发逻辑---**适配测试建议**:```bash#测试命令adbshellambroadcast-acom.example.app.INTERNAL_ACTION-pcom.example.app```§§相关问题§§1.如何确保自定义广播Android15上的兼容性?2.静态广播接收器在Android14有哪些额外限制?3.除了广播Android组件通信有哪些最佳实践?[^1]:Android广播机制需声明导出属性[^3]:Android14动态注册广播必须声明导出标志[^4]:适配Android后台广播限制</think> 以下是Android自定义广播的完整使用实例,结合Android 13-15的适配要点,帮助您安全高效地实现应用内通信: ### 一、自定义广播完整使用实例 #### 1. 动态注册广播(带版本适配) ```kotlin // 定义自定义广播Action const val INTERNAL_BROADCAST_ACTION = "com.example.app.INTERNAL_ACTION" class MainActivity : AppCompatActivity() { private lateinit var receiver: BroadcastReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 1. 创建广播接收器 receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == INTERNAL_BROADCAST_ACTION) { val message = intent.getStringExtra("msg") Toast.makeText(context, "收到广播: $message", Toast.LENGTH_SHORT).show() } } } // 2. 动态注册(兼容Android 13+) val filter = IntentFilter(INTERNAL_BROADCAST_ACTION) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13+必须声明导出标志 registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED) // 应用内广播 } else { registerReceiver(receiver, filter) } // 3. 发送广播按钮 findViewById<Button>(R.id.btn_send).setOnClickListener { sendInternalBroadcast() } } // 发送应用内广播(适配后台限制) private fun sendInternalBroadcast() { val intent = Intent(INTERNAL_BROADCAST_ACTION).apply { putExtra("msg", "Hello from MainActivity!") // Android 8.0+需要设置包名避免后台限制 setPackage(packageName) // 关键适配点[^4] } sendBroadcast(intent) } override fun onDestroy() { super.onDestroy() unregisterReceiver(receiver) // 解注册 } } ``` #### 2. 静态广播声明(AndroidManifest.xml) ```xml <!-- 必须声明android:exported属性 --> <receiver android:name=".StaticReceiver" android:exported="false"> <!-- 应用内广播设为false --> <intent-filter> <action android:name="com.example.app.STATIC_ACTION"/> </intent-filter> </receiver> ``` #### 3. 静态接收器实现 ```kotlin class StaticReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "com.example.app.STATIC_ACTION") { // 唤醒应用处理后台任务 val data = intent.getStringExtra("wakeup_data") Log.d("StaticReceiver", "唤醒应用: $data") } } } ``` #### 4. 从Service发送广播 ```kotlin class MyService : Service() { fun triggerBackgroundEvent() { val intent = Intent().apply { action = "com.example.app.STATIC_ACTION" putExtra("wakeup_data", "新数据到达") setPackage(packageName) // 设置包名绕过后台限制[^4] } sendBroadcast(intent) } } ``` ### 二、关键适配技术点 1. **动态注册导出标志(Android 13+)** ```kotlin // 必须二选一: registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED) // 允许外部访问 registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED) // 仅应用内[^3] ``` 2. **静态广播强制声明(Android 14+)** ```xml <!-- 缺少exported声明会导致安装失败 --> <receiver android:name=".MyReceiver" android:exported="false"/> ``` 3. **后台广播限制解决方案** - 发送时必须指定包名: ```java intent.setPackage(context.getPackageName()); ``` - 使用显式Intent(指定组件类名) - 改用WorkManager处理后台任务 4. **PendingIntent适配(Android 12+)** ```kotlin val pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE // 必须声明可变性[^3] ) ``` ### 三、广播替代方案(推荐) ```mermaid graph TD A[组件通信需求] --> B[应用内通信] A --> C[跨进程通信] B --> D[LocalBroadcastManager] B --> E[LiveData/Flow] B --> F[EventBus] C --> G[ContentProvider] C --> H[AIDL] ``` #### LiveData替代方案示例 ```kotlin // 创建全局事件总线 object AppEventBus : ViewModel() { private val _events = MutableLiveData<Event>() val events: LiveData<Event> = _events fun postEvent(event: Event) { _events.postValue(event) } } // 发送事件 AppEventBus.postEvent(Event("DATA_UPDATE")) // 接收事件 AppEventBus.events.observe(this) { event -> when (event.type) { "DATA_UPDATE" -> updateUI() } } ``` ### 四、调试技巧 1. **广播测试命令** ```bash adb shell am broadcast -a com.example.app.INTERNAL_ACTION -p your.package.name ``` 2. **后台限制检测** ```logcat W/BroadcastQueue: Background execution not allowed ``` ### 五、常见问题解决 **Q:广播Android 14上无法接收?** - 检查`AndroidManifest.xml`中所有`<receiver>`是否都声明了`android:exported` - 确认发送时调用了`intent.setPackage()` **Q:动态注册报错`SecurityException`?** ```kotlin // 缺少RECEIVER_NOT_EXPORTED声明时触发 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED) // 修复方案[^3] } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值