Android5.0后服务禁止使用隐式启动

Android 5.0之后禁止使用隐式启动服务

  • 这段时间维护一段老代码,发现在低版本上的手机上没问题,在5.0之后的手机出现下列错误: Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.xxx.xxx.xxx.xxx (has extras) } 可是我去配置文件中看的话明明是定义了这个服务的Action呀,最后找了半天原来是5.0之后服务不能以前那样直接隐式启动,需要指定Intent的setPackage(“包名”),或者指定Intent的ComponentName信息:intent.setComponent(xxx).

  • 两种方法如下

    方法一:
    Intent serviceIntent = new Intent();
    serviceIntent.setActio("你的服务action");
    serviceIntent.setPackage(你的应用的包名");
    context.startService(serviceIntent);
    
    方法二
    Intent serviceIntent = new Intent();
    ComponentName componentName = new ComponentName(你的应用的包名,serviceName);
    serviceIntent.setComponent(componentName);
    context.startService(serviceIntent);
    

    在这里记录一下以便后面遇到了这个问题可以查询.

<think>好的,我现在需要详细讲解Android中的Broadcast Receiver,包括它的作用、使用方法以及举例说明。首先,我应该回忆一下Broadcast Receiver的基本概念,确保自己理解正确。Broadcast Receiver是Android四大组件之一,主要用于接收系统或应用发出的广播消息,并做出响应。 接下来要确定它的主要作用。Broadcast Receiver可以用来监听系统事件,比如电量变化、网络状态改变、短信接收等,也可以用于应用内部或应用之间的通信。需要分点说明这些作用,让用户清楚其应用场景。 然后是使用方法。需要分静态注册和动态注册两种情况来讲解。静态注册是在AndroidManifest.xml中声明,这样应用即使未运行也能接收广播,比如开机启动。动态注册是在代码中通过registerReceiver()方法注册,通常与组件的生命周期绑定,如Activity的onResume和onPause,避免资源泄露。 需要强调Android 8.0(API 26)之后对静态注册的限制,比如不能注册大部分系统广播,这部分容易出错,要提醒开发者注意。同时,动态注册的优缺点,比如灵活但需手动管理生命周期。 接下来是使用步骤,可能分为注册Receiver、创建BroadcastReceiver子类、发送广播三个部分。每个步骤需要具体说明,比如静态注册的xml写法,动态注册的代码示例。发送广播部分要说明如何发送标准广播和有序广播,使用sendBroadcast()和sendOrderedBroadcast()的区别,以及如何传递数据。 例子部分需要举两个典型例子,比如动态注册监听网络变化,静态注册实现开机启动。这两个例子能覆盖动态和静态的使用场景,同时涉及系统广播和自定义广播。要确保代码示例正确,比如权限声明,接收器的实现,以及注册方。 需要注意权限问题,比如接收系统广播可能需要声明权限,发送自定义广播时也可以添加权限控制。另外,有序广播的处理和优先级设置,以及如何终止广播的传递,这些高级用法可以简要提及,帮助用户更深入理解。 可能还需要提到Local Broadcast Manager的使用,用于应用内部广播,提高安全性,避免其他应用的干扰。但自Android Jetpack以来,可能推荐使用LiveData或其他方替代,这点可以提一下,但主要聚焦在Broadcast Receiver本身。 检查是否有遗漏的重要点,比如显广播和广播的区别,Android版本差异带来的影响,以及确保示例代码的正确性,比如正确的IntentFilter动作,正确的权限声明,避免常见的错误,如动态注册后未注销导致的内存泄漏。 最后,总结Broadcast Receiver的核心作用,使用时的注意事项,以及适用场景,帮助用户形成完整的理解。需要确保语言通俗易懂,结构清晰,步骤明确,示例实用,能够帮助开发者实际应用。</think>Broadcast Receiver 是 Android 四大组件之一,主要用于**监听系统和应用的广播消息**,相当于 Android 系统中的"全局事件监听器"。以下是详细讲解: --- ### 一、核心作用 1. **系统事件监听** 接收系统级事件:充电状态变化、时区变更、屏幕亮灭、低电量提醒等 `示例:监听网络状态变化自动重连` 2. **应用间通信** 不同应用间通过广播传递数据(需注意权限控制) `示例:电商APP通知物流APP更新配送状态` 3. **应用内部通信** 组件间解耦通信(推荐使用 LocalBroadcastManager) `示例:Activity通知Fragment刷新界面` --- ### 二、两种注册方 #### ▶ 静态注册(Manifest声明) 特点:应用未启动也能接收广播,适合监听系统事件 ```xml <receiver android:name=".MyReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> ``` ⚠️ **Android 8.0+限制**:除部分白名单广播外,禁止大多数静态注册 #### ▶ 动态注册(代码注册) 特点:灵活控制生命周期,需手动注册/注销 ```kotlin val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { // 处理逻辑 } } val filter = IntentFilter().apply { addAction(ConnectivityManager.CONNECTIVITY_ACTION) } // 注册(通常在onResume) context.registerReceiver(receiver, filter) // 注销(必须在onPause或onDestroy) context.unregisterReceiver(receiver) ``` --- ### 三、广播类型 | 类型 | 特点 | 发送方法 | |---------------|-----------------------------|-----------------------| | 标准广播 | 异步执行,所有接收器同时接收 | sendBroadcast() | | 有序广播 | 顺序传递,可终止/修改数据 | sendOrderedBroadcast()| | 粘性广播 | 已弃用(Android 5.0+) | 不推荐使用 | --- ### 四、完整使用示例 #### 场景:监听网络状态变化 1. **动态注册接收器** ```kotlin class NetworkReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager val networkInfo = cm.activeNetworkInfo if (networkInfo?.isConnected == true) { when(networkInfo.type) { ConnectivityManager.TYPE_WIFI -> showToast("WIFI已连接") ConnectivityManager.TYPE_MOBILE -> showToast("移动网络已连接") } } else { showToast("网络断开") } } } ``` 2. **注册与注销** ```kotlin class MainActivity : AppCompatActivity() { private lateinit var receiver: NetworkReceiver override fun onResume() { super.onResume() receiver = NetworkReceiver() registerReceiver(receiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)) } override fun onPause() { super.onPause() unregisterReceiver(receiver) } } ``` 3. **添加权限** ```xml <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ``` --- ### 五、发送自定义广播 #### 发送端: ```kotlin val intent = Intent().apply { action = "com.example.MY_CUSTOM_ACTION" putExtra("msg", "Hello Broadcast!") } sendBroadcast(intent) // 标准广播 // sendOrderedBroadcast(intent, null) // 有序广播 ``` #### 接收端: ```xml <!-- 静态注册需在Manifest声明 --> <intent-filter> <action android:name="com.example.MY_CUSTOM_ACTION"/> </intent-filter> ``` --- ### 六、高级用法 1. **权限控制** ```kotlin // 发送带权限广播 sendBroadcast(intent, "com.example.PERMISSION") // 接收器声明权限 <receiver android:name=".MyReceiver" android:permission="com.example.PERMISSION"> ... </receiver> ``` 2. **有序广播处理** ```kotlin // 设置优先级(-1000~1000) <intent-filter android:priority="100"> <action android:name="com.example.ORDERED_ACTION"/> </intent-filter> // 终止广播传递 abortBroadcast() // 修改数据 setResultData("Modified Data") ``` --- ### 七、最佳实践 1. **避免长时间操作**:onReceive() 在主线程运行,超过10秒会导致ANR 2. **使用LocalBroadcastManager**(已过时)替代方案: - LiveData 事件总线 - RxJava/RxAndroid - 第三方事件总线库(如EventBus) 3. **注意广播安全**:避免接收恶意广播,exported属性设置为false(不需要跨应用时) --- 通过合理使用 Broadcast Receiver,可以实现高效的系统事件响应和组件间通信,但要注意避免滥用导致性能问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值