新闻详情

新闻详情

首页 / 资讯中心 / 详情

Android Intent Filter 实战:进入分享与打开方式列表

发布时间:2026/10/2 5:20:57来源:尧图网络
Android Intent Filter 实战:进入分享与打开方式列表
做过安卓开发的人大概都碰过这种场面用户在相册里选中一张图点一下分享弹出来的应用列表里微信、微博、QQ 排得整整齐齐自己辛苦写了三个月的应用连个影子都没有。反过来做产品的人又会追问为什么别人的应用能稳坐在系统分享面板的第一排我们却要翻到更多里才能找到这件事的答案就藏在安卓那套 Intent Filter 与 Intent 解析机制里。所谓将自己的应用加入到其他应用列表本质是让你的应用被系统和其他应用发现——别人发起一个动作时系统能在候选名单里找到你并且把你摆在合适的位置上。这篇内容面向的是已经能写 Activity、能跑通基本项目的安卓开发者也包括用 uni-app 这类跨端框架做上架的朋友。我会把能被发现这件事拆成四层分清系统里到底有几张列表、搞懂匹配规则、弄明白排序与直达入口、最后落到一份可以直接抄的工程配置上。整篇不聊虚的全部围绕一个核心问题展开为什么有些应用处处都在而你写的那个偏偏不在。1. 先搞清楚其他应用列表到底指哪几张列表很多人一上来就写intent-filter结果加完发现弹出来的列表里还是没有自己。问题往往不在代码而在于他根本没弄清自己想去的是哪张列表。安卓系统里能被称作应用列表的地方至少有四五处每一处背后对应的 action 和匹配条件都不一样混在一起谈就必然踩坑。1.1 分享列表由 ACTION_SEND 撑起的半壁江山分享列表是整个体系里存在感最强的一张。用户在任意应用里点分享系统实际上是在拿一个Intent.ACTION_SEND去找所有声明了这个 action 的应用。文本分享是最常见的形态但真正的战场在图片和视频上——因为这两类内容量大、用户分享频率高谁抢到了这个入口谁就拿到了流量。想让自己的应用出现在分享列表里光声明ACTION_SEND是不够的还要把mimeType说清楚。如果你只想要图片那就声明image/*想要视频声明video/*两者都要就写两个data标签。这里有个很常见的误解有人写了*/*以为能通吃结果发现分享纯文本时自己出现了分享图片时反而没出现。原因在于部分系统的分享器会对*/*做二次过滤尤其是带EXTRA_STREAM的场景系统更倾向于展示明确了具体 MIME 类型的目标。所以我一般建议业务允许的前提下把image/*、video/*这类具体类型写全别偷懒用一个通配符糊过去。还有一点值得单独拎出来说ACTION_SEND是单文件分享ACTION_SEND_MULTIPLE才是多文件。用户一次选九张图分享时系统发的是ACTION_SEND_MULTIPLE。如果你只注册了前者那就只能接住单张图多选场景下你依然不在列表里。这两个 action 建议一起注册代价很低覆盖的场景却翻了一倍。1.2 打开方式列表ACTION_VIEW 与 MIME 匹配第二张重要的列表是打开方式。用户点开一个 PDF、一段音频、一个自定义后缀的文件系统会问用什么打开这时候候选的应用就是声明了ACTION_VIEW并且 MIME 或后缀匹配的那批。这张列表和分享列表最大的区别在于它的触发往往来自系统文件管理器或者浏览器Intent 里通常会带有content://或file://的 Uri。这就要求你的data不仅要写mimeType很多时候还要写scheme。只写mimeType不写scheme的写法在部分定制系统上会失效因为系统解析时是拿 Intent 里的 scheme 去逐个比对的。我个人的习惯是只要涉及文件打开就写成组合形式intent-filter action android:nameandroid.intent.action.VIEW / category android:nameandroid.intent.category.DEFAULT / category android:nameandroid.intent.category.BROWSABLE / data android:schemecontent / data android:schemefile / data android:mimeTypeapplication/pdf / /intent-filter这里BROWSABLE要不要加取决于你是否希望浏览器里点击链接也能唤起。加了它网页里点到对应 MIME 的链接时你的应用会进候选名单不加就只有本地文件能唤起。这是一个典型的多做一步覆盖更广的取舍按业务需要决定。1.3 系统设置里的默认应用与打开支持的链接第三张列表不在弹窗里而在系统设置的深层菜单里。当你注册了多个同类 MIME 之后系统会在默认应用里列出你用户可以把某一类文件的默认打开方式设成你的应用。这个设置项一旦生效用户的体验会从每次都问变成直接进你的应用转化率的差距是很明显的。和它配套的还有打开支持的链接这个开关对应的是 App Links 机制。如果你的应用用了http或https的域名并开启了android:autoVerifytrue系统会去拉取服务器上的数字资产链接文件做校验校验通过之后用户点击你域名下的链接就会直接进应用连选择列表都不弹。这是所有入口里最霸道的一种但门槛也最高——你得真的拥有那个域名而且域名下要能放文件。1.4 Android 11 之后新增的变量包可见性从 Android 11API 30开始系统对应用的视野做了限制。默认情况下你的应用看不到其他已安装的应用queryIntentActivities返回的结果会被系统过滤。这个变化对被别人发现本身没有影响——你注册的 intent-filter 依然生效别人依然能调起你。它影响的是反向查询如果你的应用需要主动去查系统里有哪些应用能处理某个 Intent就会拿到不完整的结果。处理方式是在 Manifest 里声明queries元素把你关心的包名或 Intent 签名写进去。比如你要查所有能接收图片分享的应用queries intent action android:nameandroid.intent.action.SEND / data android:mimeTypeimage/* / /intent /queries注意不要为了图省事直接声明QUERY_ALL_PACKAGES权限。各大应用市场对它的审核都很严格除非你的应用核心功能确实依赖包枚举比如安全类、启动器类否则大概率会被打回。2. Intent Filter 的匹配规则为什么你写了却没出现清单写对了只是第一步。真正决定出现在哪张列表的是系统那套挑剔的匹配算法。这套算法有明确的规则但坑就藏在规则的细节里——很多开发者写完以为万事大吉实际是某一项没对上整个过滤器直接失配。2.1 action 是入口category 是门票匹配的本质是三个维度的交叉验证action、category、data。三者之间是与的关系任何一项对不上这个 intent-filter 就不会被选中。action 最好理解Intent 里的 action 必须在 filter 里存在对应的声明一条不匹配就出局。但 category 的规则稍微绕一点它遵循的是一条不对称的规则Intent 中携带的每一个 category都必须在 filter 里被声明但 filter 里声明的 category 可以比 Intent 多。这意味着filter 里多写几个 category 是无害的写少了才会出事。比如系统在发起ACTION_SEND时通常会带上CATEGORY_DEFAULT如果你的 filter 只写了 action 没写CATEGORY_DEFAULT匹配就会失败。所以你会看到几乎所有标准示例里都有这么一行category android:nameandroid.intent.category.DEFAULT /这是隐式 Intent 的默认约定凡是希望通过隐式 Intent 被启动的组件都建议带上它。我踩过一次坑某次重构时误删了这一行结果本地调试一直好的功能在某个定制 ROM 上完全失效排查了半天才反应过来。2.2 data 匹配是三段式很多人栽在这里data 的匹配是三张列表intent-filter里所有data标签的mimeType汇总成一张表所有scheme汇总成一张表host、port、path再各自成表。系统拿 Intent 里的对应部分去比对只要 MIME 匹配上了scheme 就不再做强制要求——这是很多人不知道的一条反直觉规则。举个例子Intent 里如果只有 MIME 没有 Uri那你的 filter 里只要有一个data android:mimeType...就能匹配上scheme 写不写都无所谓。反过来如果 Intent 里带的是 Uri那 MIME 就会从 Uri 里推导出来参与匹配。这也解释了为什么有些应用注册了schemecontent却接不到分享请求——因为分享 Intent 走的是 MIME 匹配路径跟 scheme 没关系。一个必须记住的例外如果一个 intent-filter 完全没有声明任何data标签那它只能匹配不带 data 的 Intent。反之只要声明了 data就必须在 data 维度匹配成功。这个规则决定了你不能用一个万能 filter同时接住纯文本和文件。匹配维度Intent 中的值Filter 中的声明结果actionACTION_SENDACTION_SEND通过categoryDEFAULT未声明 DEFAULT失败MIMEimage/pngimage/*通过MIMEtext/plainimage/*失败data无 Uri声明了 scheme通过MIME 已匹配data有 Uri未声明任何 data失败2.3 多个 data 标签是或多个属性是且这一条是写 intent-filter 时最容易写错的地方。当你写data android:mimeTypeimage/* / data android:mimeTypevideo/* /两个独立的data标签之间是或的关系表示既能接图片也能接视频。但如果你写成一个标签里塞两个属性data android:mimeTypeimage/* android:schemecontent /那mimeType和scheme之间是且的关系必须同时满足。很多人想表达图片或视频结果写成了同一个标签里的多属性语义就完全变了。我见过一个真实案例某应用的分享入口在当前版本上直接消失了最后查到原因就是两个data被 IDE 的格式化合并成了一行多属性MATCH 逻辑从或变成了且而分享 Intent 通常只有 MIME 没有 scheme于是全部失配。实操心得涉及多类型支持时养成一行一个data的习惯哪怕会被代码格式化工具合并也手动拆回来。这个细节在代码评审里也值得单独看一眼。2.4 一段可以直接抄的 Manifest 配置把上面几条规则揉在一起一个相对完整的分享打开配置长这样activity android:name.ui.ShareEntryActivity android:exportedtrue android:labelstring/app_name android:themestyle/Theme.Transparent intent-filter android:labelstring/share_target_label action android:nameandroid.intent.action.SEND / category android:nameandroid.intent.category.DEFAULT / data android:mimeTypeimage/* / data android:mimeTypevideo/* / /intent-filter intent-filter android:labelstring/share_target_label action android:nameandroid.intent.action.SEND_MULTIPLE / category android:nameandroid.intent.category.DEFAULT / data android:mimeTypeimage/* / data android:mimeTypevideo/* / /intent-filter intent-filter android:labelstring/open_target_label action android:nameandroid.intent.action.VIEW / category android:nameandroid.intent.category.DEFAULT / data android:schemecontent / data android:schemefile / data android:mimeTypeimage/* / /intent-filter /activity注意android:exportedtrue这一行。从 Android 12API 31开始凡是声明了 intent-filter 的组件都必须显式指定exported属性否则会在编译期直接报错。这是一个硬性要求没有绕过去的办法。另外android:theme我用了一个透明主题目的是让分享入口 Activity 在处理完数据后立刻跳转到主界面不留下一个突兀的白屏这个细节对体验的影响比想象中大。3. 从能出现到排前面排序逻辑与直达入口出现在列表里只是及格线能不能排在前面才是真正的胜负手。系统排序这件事官方从来没有给过完整的公开算法但从实际表现和一些可观测的行为来看规律还是有的。3.1 系统排序到底看什么在大多数原生和类原生系统上短时间内被调用得越频繁的目标排序越靠前。系统会记录每个 Intent 解析结果的使用频次形成一个隐式的权重表。这解释了为什么你第一次装某个应用时它在列表末尾用了几次之后就爬上来了。除了频次还有几个因素会明显影响位置。一是直接分享Direct Share提供的直达入口这类入口会以头像昵称的形式固定出现在分享面板顶部视觉权重远高于普通应用图标。二是系统对用户手动置顶的支持部分 ROM 允许长按应用图标选择置顶这个偏好会被持久化。三是应用的android:label和图标质量某些定制系统在做无权重排序时会按字母序排列此时一个好的名称能让你靠前一点。需要清醒的一点是前两条你控制不了多少能主动优化的空间主要在 Direct Share 和标签命名上。把精力放对地方比盲目调 Manifest 有用得多。3.2 直接分享Sharing Shortcuts 的落地写法Direct Share 是所有入口里转化率最高的因为它把选中应用和选中应用内的某个联系人/会话合并成了一步。用户在分享面板里直接点某个头像就跳进了你的应用并带上了目标对象。早年间这套机制依赖ChooserTargetServiceAndroid 10 之后官方把它替换成了 Sharing Shortcuts用ShortcutManagerCompat发布动态快捷方式。核心步骤有三步构建带setLongLived(true)的 ShortcutInfoCompat、设置setCategories为一个包含分享类别的集合、最后调用pushDynamicShortcut推送到系统。系统会在下次打开分享面板时自动把这些快捷方式渲染成直达入口。这里有几个容易卡住的点。第一快捷方式必须标记为 long-lived否则系统会在会话结束后清理掉。第二发布的数量建议控制在系统上限内通常不超过几个数量太多系统反而会全部降级成普通入口。第三每个快捷方式都要携带一个能定位到具体目标的 Intent这个 Intent 的 action 需要和你的分享 Activity 能接住的 action 一致否则点进去会找不到人。3.3 快捷方式、App Actions 与深链接的组合除了 Direct Share还有两条路能把用户直接送进你的应用。第一条是长按图标弹出的快捷方式也就是ShortcutManager的静态和动态快捷方式。第二条是深链接用户点击某个特定 URL 时直接进应用。这三套机制在底层其实共享同一套 Intent 解析能力区别只在触发源。我一般会这么规划深链接负责外部流量入口静态快捷方式负责高频功能的快速到达动态快捷方式配合 Direct Share 负责社交场景。三者不冲突同一份业务逻辑可以被三个入口复用开发成本主要集中在入口 Activity 的参数解析上。有一个细节值得注意Android 14 对隐式 Intent 做了一轮收紧应用向外部组件发送隐式 Intent 时如果目标组件没有 exported会直接被系统拦下。这条规则主要影响的是你发出去的 Intent 能不能到达别人但反过来也提醒我们作为接收方组件必须正确 exported 才能被外部唤起。这在做多模块拆分时特别容易漏比如把分享 Activity 挪到了某个 library 模块结果那个模块的 Manifest 合并顺序导致 exported 被覆盖。3.4 让分享面板显示正确的图标和名称很多开发者会忽略一件事分享面板里显示的那个应用名取的是intent-filter上的android:label而不是应用名。如果你没单独设置它才会回退到应用级 label。这就给了我们一个操作空间——分享入口可以显示成保存到某某这样的动作描述比直接显示应用名更容易被用户理解。图标同理优先取 filter 上的android:icon没有才回退。建议给分享入口单独配一个辨识度高的图标尺寸和系统图标保持一致避免在面板里显得格格不入。这类视觉细节在应用市场推广素材里也常常被拿来对比属于低成本高感知的优化项。4. 完整实操做一个图片压缩器被全网调用前面讲的都是原理这一节把它串成一个能跑起来的完整工程。目标很明确做一个能被任意应用调起的图片处理应用用户从相册分享图片过来我们在应用内压缩完再返回或保存。4.1 工程与依赖准备创建一个标准的安卓工程最低 API 建议定在 24 以上这样既能覆盖绝大多数设备又能用上较新的 Intent 处理 API。依赖方面需要androidx.core:core-ktx用于 FileProvider 和 ShortcutManagerCompat加上协程库处理压缩这种耗时任务。dependencies { implementation(androidx.core:core-ktx:1.13.1) implementation(org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0) }工程结构上我会把入口 Activity 单独放在ui.share包里跟主流程隔开。这样做的理由是入口 Activity 的生命周期很特殊——它可能在任何任务栈里被启动也可能在应用完全没运行的情况下被拉起来跟主界面混在一起容易出状态管理问题。4.2 Manifest 全量配置完整配置包括入口 Activity、FileProvider 和必要的 queries 声明application activity android:name.ui.share.ShareEntryActivity android:exportedtrue android:labelstring/share_label android:themestyle/Theme.Transparent android:excludeFromRecentstrue intent-filter android:labelstring/share_label action android:nameandroid.intent.action.SEND / category android:nameandroid.intent.category.DEFAULT / data android:mimeTypeimage/* / /intent-filter intent-filter android:labelstring/share_label action android:nameandroid.intent.action.SEND_MULTIPLE / category android:nameandroid.intent.category.DEFAULT / data android:mimeTypeimage/* / /intent-filter /activity provider android:nameandroidx.core.content.FileProvider android:authorities${applicationId}.fileprovider android:exportedfalse android:grantUriPermissionstrue meta-data android:nameandroid.support.FILE_PROVIDER_PATHS android:resourcexml/file_paths / /provider /applicationandroid:excludeFromRecentstrue这一行是我强烈建议加的。分享入口 Activity 属于中转处理完就跳走了如果它进了最近任务列表用户切回去会看到一个已经结束的界面体验很奇怪。4.3 Activity 接住 Intent 并解析数据入口 Activity 的核心任务是判断 Intent 类型、取出数据、做处理、决定跳转还是返回。下面是一段可以直接用的解析逻辑class ShareEntryActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) when (intent?.action) { Intent.ACTION_SEND - handleSingle(intent) Intent.ACTION_SEND_MULTIPLE - handleMultiple(intent) else - finishSafely() } } private fun handleSingle(intent: Intent) { val uri if (Build.VERSION.SDK_INT Build.VERSION_CODES.TIRAMISU) { intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java) } else { Suppress(DEPRECATION) intent.getParcelableExtra(Intent.EXTRA_STREAM) } ?: return finishSafely() val mime intent.type ?: contentResolver.getType(uri) ?: image/* launchProcessor(listOf(uri), mime) } private fun handleMultiple(intent: Intent) { val uris if (Build.VERSION.SDK_INT Build.VERSION_CODES.TIRAMISU) { intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java) } else { Suppress(DEPRECATION) intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM) } ?: return finishSafely() if (uris.isEmpty()) return finishSafely() val mime intent.type ?: image/* launchProcessor(uris, mime) } }这里有一个必须处理的兼容性问题getParcelableExtra的旧签名在 Android 13API 33之后被标记为废弃新签名要求传入 Class 对象。很多老代码在新系统上会直接返回 null然后用户会发现分享过来了但应用闪退或者没反应。上面这段用版本判断做了兼容是当前阶段比较稳妥的写法。还有个细节Intent.EXTRA_STREAM里的 Uri 是对方应用通过 FileProvider 暴露出来的临时授权。你不能假设这个 Uri 永久可读也不能在 Activity 销毁后继续用。正确做法是在onCreate里立刻把它拷贝到自己的缓存目录或者用contentResolver.openInputStream当场读完。我见过有人把这个 Uri 存进数据库第二天来读直接报权限异常这就是没理解授权生命周期的后果。4.4 多文件分享与 FileProvider 配置处理完之后如果要回传给别的应用就需要自己的 FileProvider。配置文件放在res/xml/file_paths.xmlpaths cache-path nameshared_images pathshared/ / files-path nameinternal_images pathimages/ / /paths回传时构造 Intent 并在最后加上读权限标志fun shareBack(uri: Uri, mime: String) { val send Intent(Intent.ACTION_SEND).apply { type mime putExtra(Intent.EXTRA_STREAM, uri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } startActivity(Intent.createChooser(send, getString(R.string.chooser_title))) finish() }FLAG_GRANT_READ_URI_PERMISSION这个标志不能省。加上它接收方应用才能读到你通过 FileProvider 暴露的文件。省了它对方拿到的就是一个无权限的 Uri打开直接失败。这个坑的迷惑性在于它在某些系统上可能碰巧能工作让你以为代码没问题。多文件回传时要用ACTION_SEND_MULTIPLE配合putParcelableArrayListExtra并且同样需要授权标志。另外从 Android 10 开始直接使用file://的 Uri 会触发FileUriExposedException所有跨应用的文件传递都必须走content://这一点在迁移老项目时特别容易翻车。4.5 adb 验证与实机测试写完了别急着拿手机点先在命令行验证一下系统到底认不认你的配置# 查看你的应用注册了哪些 Intent Filter adb shell dumpsys package com.example.compressor | grep -A 30 Non-Data Actions # 直接查询谁能处理图片分享 adb shell cmd package query-activities -a android.intent.action.SEND -t image/png # 模拟一次图片分享把图片推到设备上再发 Intent adb push test.jpg /sdcard/Download/test.jpg adb shell am start -a android.intent.action.SEND -t image/jpeg \ --eu android.intent.extra.STREAM file:///sdcard/Download/test.jpg第二条命令特别有用它直接列出当前系统中所有能响应图片分享的 Activity。如果你的应用不在输出里那问题一定在 Manifest 层面不用去怀疑业务代码。这个排查顺序能帮你省下大量时间——先确认能不能被发现再去看发现了之后处理得对不对。最后一条命令在部分新系统上会因为 file:// 限制而失败可以改用 mediastore 的 content Uri 来测试。实机测试时建议准备三个不同品牌的设备因为定制 ROM 对分享面板的实现差异不小尤其在SEND_MULTIPLE的处理上有些系统会把它拆成多次SEND调用这时候你的代码要能同时应付两种路径。5. 排查清单应用不出现在列表里的 9 种原因排查这件事最怕的是东一榔头西一棒子。我把自己这些年遇到过的问题整理成了一套固定顺序从 Manifest 到运行时逐个过基本能覆盖九成以上的情况。5.1 Manifest 层静态排查先看最基础的几项。第一intent-filter是不是写在了activity里面而不是application里写错位置的话编译能过但系统完全看不到。第二exported是否为 true从 Android 12 开始这是必填项写错会在安装时就被拦下。第三action 名称有没有拼错android.intent.action.SEND里少一个字母系统不会报错只会静默失配。再看 category。CATEGORY_DEFAULT缺失是最高频的元凶尤其是在手写 Manifest 或者做模块合并的时候。第四检查是否声明了CATEGORY_DEFAULT。第五检查mimeType是否和实际场景对得上分享图片时系统发的 MIME 可能是image/jpeg也可能是image/*推导出来的具体值用image/*声明才能稳定匹配。第六和第七项跟打包有关。如果你的应用做了多渠道或者模块化Manifest 会被合并合并规则里tools:node属性可能悄悄移除了你的 filter。检查最终 APK 里的 Manifest 是最可靠的办法可以用构建产物目录下的merged_manifest文件核对也可以直接把 APK 拖进分析工具看。这不是鼓励去抄别人而是确认自己的配置没被工具链改掉。5.2 命令行与日志动态排查Manifest 确认无误之后进入运行时排查。第八项看日志里有没有ActivityNotFoundException或者解析失败相关的警告很多问题在 Logcat 里其实是有痕迹的只是被淹没在大量输出里。过滤IntentResolver或者PackageManager关键字往往能看到系统在做匹配决策时的细节。第九项确认设备上是否存在多个用户空间或者工作资料Work Profile。在企业设备上应用可能被安装在某个受管空间里而分享面板默认只显示当前空间的应用。这种情况在消费级设备上少见但做企业应用时是必查项。排查心得把上面九项做成一张检查表贴在工位上遇到问题从头到尾过一遍比凭直觉乱改代码快得多。我自己的经验是前六项能解决 80% 的问题剩下 20% 才需要动命令行。5.3 常见问题速查表症状最可能的原因快速验证方式分享面板完全没有自己缺少 CATEGORY_DEFAULT检查 Manifest补上后再装单图能分享多图不行未注册 SEND_MULTIPLE补充对应 filter只在部分机型出现MIME 用了通配符改成具体类型如 image/*安装时报 Manifest 错误exported 未显式声明补上 true 或 false点进来后闪退Uri 授权已过期检查是否立即可读取分享回去对方打不开缺少读权限标志加 FLAG_GRANT_READ_URI_PERMISSION首次安装有更新后没了模块合并覆盖了 filter对比合并后 Manifest浏览器链接唤不起App Links 未校验通过检查域名下的校验文件查询不到其他应用Android 11 包可见性限制补 queries 声明5.4 几条踩坑心得第一条心得关于测试时机。不要等所有功能做完再验证分享入口正确的顺序是在写完 Manifest 的第一时间就用query-activities命令确认一遍。这时候改配置的成本最低等到业务逻辑堆上去之后再回来查改动的影响面会大很多。第二条关于多用户场景。我遇到过一次很诡异的 bug同一台设备上主用户能用切到访客用户就不行。最后发现是因为分享的目标 Uri 指向了主用户空间的文件访客用户没有读取权限。这类问题只在特定操作路径下复现如果不是刻意测试过很容易漏到线上。第三条关于参数校验。分享过来的 Intent 里EXTRA_STREAM、type、clipData这三个字段的组合情况有七八种很多应用只处理了最常见的那一种。稳妥的做法是写一个统一的解析函数按优先级从EXTRA_STREAM取取不到再从clipData里遍历两个都没有就安全退出别让应用崩在启动路径上。启动路径上的崩溃对用户感知最差因为用户根本没进入你的应用。6. 延伸场景TV、跨端框架与上架审核前面讲的都是手机形态但被其他应用调起这件事在别的设备形态和开发框架下有一些差异值得单独说清楚尤其是做多端适配的团队。6.1 安卓 TV 上的列表差异电视端的交互模型跟手机差别很大没有触摸屏、没有分享面板这个说法候选列表的表现形式变成了用哪个应用打开。在电视上ACTION_VIEW依然是主力但 Intent 的发起方往往是系统自带的媒体中心或者第三方播放器。这意味着你的 MIME 声明要更精确因为电视端的资源类型相对集中视频、音频、图片三类占了绝大多数。电视端还有一个特殊点CATEGORY_LEANBACK_LAUNCHER决定了你的应用能不能出现在电视的启动器里这跟手机上的CATEGORY_LAUNCHER是两个不同的入口。如果你想做一个既能在电视上被打开、又能被当成播放器调起的应用两个 category 都得声明并且要处理好遥控器焦点。定制盒子上的系统版本跨度很大从老版本到较新的安卓版本都有建议在做兼容测试时覆盖尽可能多的系统版本别只在一台设备上验证。6.2 uni-app 等跨端框架怎么写用 uni-app 这类框架做上架的团队经常问能不能不改原生工程就实现分享入口注册。答案是部分可以。uni-app 支持通过原生插件或者自定义基座的方式注入 Manifest 配置本质上还是写同一份 XML只是由框架在打包时代为合并。具体做法是在项目的原生配置目录里维护一份额外的 Manifest 片段声明你的 intent-filter然后通过自定义基座打包。需要注意的是框架的默认模板里往往已经声明了一些 filter合并时要留意冲突。常见冲突点是CATEGORY_DEFAULT被重复声明虽然重复声明本身无害但如果框架模板里用了tools:noderemove之类的指令就可能把你的配置一并移除。另一个现实问题是调试。跨端框架的调试链路比原生长入口 Activity 收到的 Intent 要先经过框架的启动层再转成页面路由参数。这个转换过程中复杂类型比如多文件 Uri 列表容易丢失。我的建议是如果分享是核心功能尽量用原生插件处理数据接收处理完再通过事件机制把结果传给 JS 层别指望框架的自动转换能覆盖所有情况。6.3 上架应用市场容易被卡的点最后聊几句上架。分享类功能在应用市场审核时属于敏感度高一点的场景因为它涉及跨应用数据传递。审核方主要看两件事你有没有声明不必要的权限以及你传递的数据有没有合规处理。权限方面前面提到的包可见性权限是重灾区。如果你的 Manifest 里出现了全域包查询的权限而应用功能并不需要大概率会被要求说明用途甚至退回。建议只声明真正用到的queries片段。数据方面用户通过分享传进来的图片或文件处理完之后要及时清理缓存别长期留在应用目录里这既是隐私要求也能避免用户投诉存储占用。备案和资质这块社交分享类功能在某些市场会被要求提供额外材料这个提前了解清楚别等审核卡住了才去补。我见过团队因为没提前准备功能都做完了一个月上不了线返工成本很高。回过头看把自己塞进别人的应用列表技术门槛其实不算高难的是把每一个细节都照顾到——匹配规则、授权生命周期、系统版本差异、各家 ROM 的实现差别每一项都可能成为绊脚石。我个人的做法是把分享入口当成一条独立的链路来对待从声明到解析到回传每一步都单独写测试用例别指望主流程的测试能顺带覆盖它。这套东西一旦搭稳了后续不管是在手机、电视还是跨端框架上复用改动量都很小剩下的就是产品层面怎么把入口用得更好。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

claude-swap 自适应轮询策略完整揭秘:为何查询上千次用量仍不被 Anthropic 429 限流 2026/10/2 7:04:13

claude-swap 自适应轮询策略完整揭秘:为何查询上千次用量仍不被 Anthropic 429 限流

claude-swap 自适应轮询策略完整揭秘:为何查询上千次用量仍不被 Anthropic 429 限流 【免费下载链接】claude-swap Switch between multiple Claude Code accounts, with automatic rate-limit rotation, usage dashboard, and parallel sessions 项目地址: https…

阅读更多 →
深度剖析 Hutool ObjectUtil 2026/10/2 7:04:13

深度剖析 Hutool ObjectUtil

前言 在 Java 日常开发中,NullPointerException(NPE)和繁琐的对象状态判断占据了大量的防御性编码时间。虽然 JDK 8 引入了 java.util.Objects,Apache Commons Lang 提供了 ObjectUtils,但在应对国内复杂的业务场景&am…

阅读更多 →
第08篇-时序数据链路-附双库实测 2026/10/2 7:04:13

第08篇-时序数据链路-附双库实测

时序数据链路:采集 → 清洗 → 存储 → 查询(附 TDengine vs ClickHouse 双库基准) 文章目录 时序数据链路:采集 → 清洗 → 存储 → 查询(附 TDengine vs ClickHouse 双库基准) 引言:影子只存"现在",调度要的是"历史" 一、先算容量账:你的平台每…

阅读更多 →
C++ map 底层与AVL 树 2026/10/2 7:04:13

C++ map 底层与AVL 树

C map 底层、AVL 树与 LeetCode 692 高频单词 —— 学习大纲本文基于手写笔记整理:std::map 接口与插入语义、LeetCode 692 前 K 个高频单词、AVL 树的定义/旋转/失衡修复。 可作为 Feynman 复习入口:先看"核心知识链",再用"主…

阅读更多 →
久坐腰不疼,但上背部靠近脖子的位置酸痛:原因分析与自测方法 2026/10/2 7:04:13

久坐腰不疼,但上背部靠近脖子的位置酸痛:原因分析与自测方法

一、问题描述 最近出现一种比较典型的情况:坐着使用电脑时,腰部基本没有明显疼痛,但是后背靠近脖子、偏上偏中间的位置持续出现酸胀、疼痛和疲劳感。坐着一段时间以后会越来越累,但站起来以后反而明显缓解。如果长期从事电脑办公、…

阅读更多 →
Madeira 触屏与物理手柄输入合并:优先级仲裁算法完整指南 2026/10/2 7:03:54

Madeira 触屏与物理手柄输入合并:优先级仲裁算法完整指南

Madeira 触屏与物理手柄输入合并:优先级仲裁算法完整指南 【免费下载链接】Madeira Run x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT 项目地址: https://gitcode.com/GitHub_Trending/mad/Madeira 在 iOS 上运行 Windows PC 游戏的 Made…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉