ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Intent 过滤(Intent Filter):让 Android 应用被其他 App 启动的完整指南

Intent 过滤(Intent Filter):让 Android 应用被其他 App 启动的完整指南 文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载本文基于《Android 官方培训课程中文版》仓库中的 basics/intents/filters.md 编写并结合仓库内 basics/intents/ 系列教程、content-sharing/sharing/receive.md 等关联章节与 Android 官方文档背景知识对 Intent Filter 的声明、匹配规则、数据处理与结果返回进行系统梳理。文中所有 XML/Java 示例均继承自原文档并补充了参数语义、匹配细节与实战经验。导读在 Android 中Intent 是连接不同应用组件的“意向说明书”。上一篇 Intent 的发送Sending the User to Another App 讲解了如何用隐式 Intent 启动其他 App本篇则从“被启动方”的视角出发讲解如何通过在 Manifest 中声明intent-filter让你的 Activity 能够响应来自其他 App 的隐式 Intent——例如当用户在相册中点击“分享”时你的社交 App 能出现在候选列表中。读完本文你将掌握 intent-filter 的 Action / Data / Category 三大匹配标准、多 filter 的组织原则、在onCreate()中读取传入 Intent 的方法以及用setResult()finish()向发起方返回结果的标准姿势。Intent Filter 的作用与工作原理前两节课Intent 的发送 与 接收 Activity 返回的结果主要讲解了从你自己的 App 启动其他 App。但反过来如果我们的 App 功能对其他 App 也有用就应该做好被调用的准备。例如如果我们创建了一个社交 App可以给好友分享消息或照片那么最好它能接收ACTION_SEND类型的 Intent——这样当用户在其他 App 触发分享功能时我们的 App 就能出现在系统弹出的候选对话框中。要实现这一点只需要在 AndroidManifest.xml 的activity标签下添加intent-filter子标签activity android:nameShareActivity intent-filter ... /intent-filter /activity其底层工作机制如下安装期注册App 被安装到设备上时系统会解析 Manifest 中所有intent-filter把这些可以处理什么 Intent的信息记录下来运行时匹配当其他 App 通过隐式 Intent 调用startActivity()或startActivityForResult()时系统会在已安装应用中进行 Intent 解析Intent resolution自动找出所有能响应该 Intent 的 Activity用户选择如果匹配到多个 Activity系统会弹出选择对话框让用户决定启动哪个如图 intents-choice.png 所示来自 Intent 的发送 一课的截图如果只匹配到一个则直接启动。因此intent-filter本质上就是一份“我愿意处理什么”的声明清单而系统扮演 Intent 与 App 之间的调度中枢。添加 Intent Filter三大匹配标准为了让 Activity 能够接收隐式 IntentIntent Filter 需要尽可能详尽地定义 Action 与 Data。一个 Intent 对象要成功匹配某个 filter需要同时满足以下三个维度对应 filter 内的三类子标签Action想执行的动作含义一个想要执行的动作名称通常是系统预定义值如ACTION_SEND、ACTION_VIEW声明方式在intent-filter内通过action子标签指定值为字符串而非 API 常量注意看下面的例子中写的是android.intent.action.SEND这个完整字符串数量一个 filter 可以声明多个actionIntent 只需匹配其中任意一个即可。DataIntent 附带的数据描述含义Intent 附带数据的描述用于约束数据的 URI 与 MIME 类型声明方式通过data子标签指定可以只定义一个或多个属性例如只指定 MIME 类型如text/plain、image/jpeg只指定 URI prefix / scheme如sms或 URI 与 MIME 类型组合使用关键细节如果不打算处理 Uri 类型数据就应该指定android:mimeType属性例如text/plain或image/jpeg。当 Intent 携带了 URI 时系统会根据 URI 推断 MIME 类型Intent 中 URI 与 MIME type 会参与对data的联合匹配。Category附加标识含义提供一种附加方式来标识 Activity 能处理的 Intent通常与用户的手势或启动位置有关声明方式通过category子标签指定默认值所有隐式 Intent 都默认带有CATEGORY_DEFAULT类别因此 filter 中必须声明它才能收到隐式 Intent详见下文常见误区。完整示例处理文本与图片的 ACTION_SEND下面是一个带 Intent Filter 的 Activity当数据类型为文本或图像时它会处理ACTION_SEND的 Intentactivity android:nameShareActivity intent-filter action android:nameandroid.intent.action.SEND/ category android:nameandroid.intent.category.DEFAULT/ data android:mimeTypetext/plain/ data android:mimeTypeimage/*/ /intent-filter /activity多个 Filter 的组织何时拆分、何时合并每个发送出来的 Intent 只会包含一个Action 与一套数据一个 URI 一个 MIME 类型但一个 Activity 的intent-filter可以声明多个action、category与data。规则是如果任何两对 action 与 data 是互相矛盾的就应该创建不同的 intent filter 来分别指定特定的 action 与 type。原因在于一个 filter 内的多个data元素之间是或的关系但 action 与 data 的组合是整体绑定的——如果两个 action 各自要求不同的 data 约束把它们塞进同一个 filter 会导致约束互相污染。典型场景假设我们的 Activity 既能处理文本/图片又能处理ACTION_SEND和ACTION_SENDTO两类 Intent。由于ACTION_SENDTOIntent 必须使用 Uri 指定接收者地址send 或 sendto需要分开定义两个 filteractivity android:nameShareActivity !-- filter for sending text; accepts SENDTO action with sms URI schemes -- intent-filter action android:nameandroid.intent.action.SENDTO/ category android:nameandroid.intent.category.DEFAULT/ data android:schemesms / data android:schemesmsto / /intent-filter !-- filter for sending text or images; accepts SEND action and text or image data -- intent-filter action android:nameandroid.intent.action.SEND/ category android:nameandroid.intent.category.DEFAULT/ data android:mimeTypeimage/*/ data android:mimeTypetext/plain/ /intent-filter /activity重要为了接收隐式 Intent必须在 Intent Filter 中包含CATEGORY_DEFAULT这个 category。startActivity()和startActivityForResult()方法会把所有 Intent 视为声明了CATEGORY_DEFAULT的类别。如果没有在 filter 中声明CATEGORY_DEFAULTActivity 将无法对隐式 Intent 做出响应——这是初学者最常见的为什么我的 App 收不到分享的根因之一。在 Activity 中处理传入的 IntentFilter 声明完毕后接下来就是在 Java 代码中决定如何处理。核心是读取启动我们 Activity 的那个 Intent使用getIntent()获取启动当前 Activity 的 Intent该方法可以在 Activity 生命周期的任何时候调用但最好在onCreate()或onStart()中执行例如onCreate()里初始化 UI 后立即读取通过intent.getData()读取携带的 Uri 数据、intent.getType()读取 MIME 类型、intent.getAction()读取 Action 字符串。示例根据 MIME 类型分发处理逻辑Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get the intent that started this activity Intent intent getIntent(); Uri data intent.getData(); // Figure out what to do based on the intent type if (intent.getType().indexOf(image/) ! -1) { // Handle intents with image data ... } else if (intent.getType().equals(text/plain)) { // Handle intents with text ... } }这个判断 action → 判断 MIME type → 取出数据的处理模式在仓库中的 接收从其他 App 传送来的数据 一节有更完整的工程化版本它先通过intent.getAction()判断是否为ACTION_SEND/ACTION_SEND_MULTIPLE再根据intent.getType()分发到handleSendText()/handleSendImage()/handleSendMultipleImages()分别用getStringExtra(Intent.EXTRA_TEXT)、getParcelableExtra(Intent.EXTRA_STREAM)、getParcelableArrayListExtra(Intent.EXTRA_STREAM)取回被分享的内容。这份代码还特别提醒由于无法预知其他 App 传来的数据量应避免在 UI 线程中处理这些数据防止大文件导致界面卡顿。返回 Result 给发起方被启动的 Activity 处理完业务后如果需要向发起方即调用startActivityForResult()的那个 Activity返回结果需要完成两个动作调用setResult()指定 result code 与 result intent调用finish()关闭当前 Activity让用户返回原来的 Activity同时系统会把结果交付给发起方的onActivityResult()回调发起方侧的完整处理流程参见 接收 Activity 返回的结果。带数据的返回示例// Create intent to deliver some kind of result data Intent result new Intent(com.example.RESULT_ACTION, Uri.parse(content://result_uri); setResult(Activity.RESULT_OK, result); finish();必须总是指定 result code。通常不是RESULT_OK就是RESULT_CANCELED。可以通过返回的 Intent 添加需要回传的数据。默认 result code 与 Back 键行为注意默认的 result code 是RESULT_CANCELED。因此如果用户在完成操作之前按下了 Back 键发起方 Activity 接收到的 result code 就是canceled。这意味即使你不主动调用setResult()返回行为也不会导致发起方崩溃只是结果被标记为取消。只返回一个 int 的简化写法如果纯粹想返回一个 int 来表示某种结果例如选择了红色这种枚举类结果可以连 Intent 都不返回直接调用只含 result code 的重载setResult(RESULT_COLOR_RED); finish();注意我们没有必要关心自己的 Activity 是被startActivity()还是startActivityForResult()方法启动的——系统会自动判断如何传递 result。在不需要 result 的情况下返回的 result 会被自动忽略因此这层逻辑完全透明。关联实战从分享到深度链接理解了基础三要素后Intent Filter 的能力边界还可以从仓库中两个真实场景得到印证场景一作为分享目标 App 接收数据在 接收从其他 App 传送来的数据 中一个 Activity 可以同时声明三个 filter分别接收单张图片SENDimage/*、纯文本SENDtext/plain和多张图片SEND_MULTIPLEimage/*。这与本课多个 filter 拆分的原则完全一致——三个 filter 各自有独立的 action data 组合互不冲突。场景二深度链接Deep Linking在 为 App 内容开启深度链接 中intent filter 还被用于让网页链接直接拉起 App 页面。其核心是ACTION_VIEWDEFAULTBROWSABLE三个要素的组合并且data需要至少包含android:scheme属性可以用android:path、android:pathPrefix等属性区分不同 URI 路径对应不同 Activity。可用adb shell am start -W -a android.intent.action.VIEW -d URI PACKAGE在设备/模拟器上测试 filter 的解析结果。这也是验证我的 filter 到底能不能匹配到该 Intent最直接的命令行手段。常见误区与调试建议综合原文档与关联章节以下是实践中最容易踩的坑误区正确做法filter 中漏掉android.intent.category.DEFAULT隐式 Intent 默认携带CATEGORY_DEFAULT必须显式声明才能收到把需要不同 data 约束的多个 action 写进同一个 filter互相矛盾的 action-data 组合应拆分到不同intent-filter处理ACTION_SENDTO却用 MIME type 约束该 Action 必须依赖 Uri scheme如sms、smsto指定接收者在onCreate()之前读取 Intent 数据尽量在onCreate()/onStart()中通过getIntent()读取忘记setResult()的默认语义不显式设置时 result code 默认为RESULT_CANCELED在 UI 线程处理大数据如分享来的大图大文件处理应放到后台线程避免 ANR如果 App收不到分享/跳转除了逐项核对上述表格还可以用adb shell am start配合-W参数构造一条目标 Intent 进行冒烟测试观察系统能否正确解析到你的 Activity详见 深度链接的测试方法。小结本篇围绕让其他 App 启动你的 Activity这一主题完整覆盖了Intent Filter 的声明位置activity下的intent-filter随安装注册进系统供隐式 Intent 解析三大匹配标准action动作字符串、dataURI/MIME 类型、category附加类别隐式 Intent 默认CATEGORY_DEFAULT多 filter 拆分原则action 与 data 组合矛盾时拆分成多个intent-filter传入 Intent 的处理getIntent()getAction()/getData()/getType()在onCreate()/onStart()中分发业务Result 返回协议setResult()finish()默认 result code 为RESULT_CANCELED纯 int 结果可省略 Intent。配合仓库中的 Intent 的发送发起方视角、接收 Activity 返回的结果结果接收方视角、接收从其他 App 传送来的数据分享接收实战与 为 App 内容开启深度链接URI 深度链接实战一起阅读即可在发送 → 过滤 → 处理 → 返回的完整链路上建立起体系化的认知。赞分享文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载相关推荐rrule.js与前端框架整合React、Vue、Angular中的最佳实践rrule.js与前端框架整合React、Vue、Angular中的最佳实践 rrule.js是一个功能强大的JavaScript库用于处理日历日期的重复规后端Expo Intent Launcher 完全指南在 React Native 中启动 Android Intent 的权威实战手册Expo Intent Launcher 完全指南在 React Native 中启动 Android Intent 的权威实战手册 导读 expo inte移动开发前端跨平台原生移动Android Intent 深度解析从显式与隐式 Intent 到 Intent Filter 的组件通信机制Android Intent 深度解析从显式与隐式 Intent 到 Intent Filter 的组件通信机制 Intent 是 Android 组件间通信文档教程知识库上一篇戴森球计划工厂蓝图完全指南从新手到专家的3000设计解决方案下一篇CANN/asc-devkit矢量加法API创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表