调用service出现Service Intent must be explicit

本文深入探讨了Android中ServiceIntent的调用方式,重点阐述了显示调用与隐式调用的原理与应用场景。特别强调了在AIDL跨进程访问Service时,如何正确使用隐式调用,并通过设置setAction()和setPackage()来实现。

 

查阅资料表明,是Android 5.0出来后,其中有个特性就是Service Intent must be explitict。本地调用使用显示调用解决,但是aidl跨进程访问service时候确实需要使用隐式调用。

隐式调用是除了设置setAction()外,还需要设置setPackage();

setPackage是设置本app的包如 :  com.fafa.pos


 


 

 

这段代码是用于将一个**隐式 Intent** 转换为**显式 Intent**,以适配 Android 5.0(API 21)及以上版本中不允许使用隐式 Intent 绑定服务的限制。下面我将详细解释这段代码的每一部分,并说明其作用和原理。 --- ### ✅ 方法签名 ```java public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) ``` - **作用**:接收一个隐式 Intent,尝试将其转换为显式 Intent。 - **参数**: - `context`:用于获取 `PackageManager`。 - `implicitIntent`:原始的隐式 Intent。 --- ### ✅ 获取 PackageManager 并查询匹配的服务 ```java PackageManager pm = context.getPackageManager(); @SuppressLint("QueryPermissionsNeeded") List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); ``` - `PackageManager` 是 Android 中用来管理应用组件的工具。 - `queryIntentServices()` 方法用于查询所有能响应这个 Intent 的服务组件。 - `@SuppressLint("QueryPermissionsNeeded")` 是为了忽略 Lint 提示,因为在 Android 8.0+ 中建议使用 `MATCH_ALL` 或 `MATCH_DEFAULT_ONLY` 等标志。 --- ### ✅ 检查匹配结果 ```java if (resolveInfo == null || resolveInfo.size() != 1) { Log.d(TAG, "createExplicitFromImplicitIntent failed"); return implicitIntent; } ``` - 只有当**恰好匹配一个服务**时才进行转换。 - 如果没有匹配或匹配多个,说明意图不明确,直接返回原 Intent(或者可以选择返回 null)。 --- ### ✅ 获取服务信息并构造 ComponentName ```java ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); ``` - 从匹配结果中取出第一个服务的包名和类名。 - 构造 `ComponentName`,用于显式指定目标组件。 --- ### ✅ 构造新的显式 Intent ```java Intent explicitIntent = new Intent(implicitIntent); explicitIntent.setComponent(component); ``` - 使用原始 Intent 的 Action、Extras 等信息创建新 Intent。 - 设置 `ComponentName`,使其成为一个**显式 Intent**。 --- ### ✅ 返回值 ```java return explicitIntent; ``` 返回构造好的显式 Intent,用于后续调用 `bindService()` 或 `startService()`。 --- ### ✅ 示例使用场景(绑定服务) ```java Intent detectServiceIntent = new Intent("com.example.CAMERA_DETECT_SERVICE"); Intent explicitIntent = createExplicitFromImplicitIntent(context, detectServiceIntent); context.bindService(explicitIntent, serviceConnection, Context.BIND_AUTO_CREATE); ``` --- ### ✅ 为什么需要这个方法? 从 **Android 5.0 (API 21)** 开始,Google 禁止使用隐式 Intent 来绑定服务(`bindService()`),以提高系统的安全性和稳定性。如果不做转换,会抛出: ``` java.lang.IllegalArgumentException: Service Intent must be explicit ``` --- ### ✅ 适用场景 - 绑定系统服务或第三方服务(你知道它存在,但不知道具体组件名) - 兼容 Android 5.0+ 设备 - 用于 AIDL 远程服务调用、系统诊断工具、设备检测模块等 --- ### ✅ 注意事项 | 项目 | 说明 | |------|------| | **匹配唯一性** | 必须确保只有一个服务匹配,否则可能绑定错误的服务 | | **权限声明** | 目标服务必须在 Manifest 中声明对应的 Intent Filter | | **兼容性** | 该方法兼容 Android 5.0 及以上版本 | | **安全性** | 如果服务是系统级或特权服务,可能需要系统权限才能访问 | --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值