小泉水头像

Android接收微信/QQ文件:从intent-filter到ContentResolver实战

做Android开发,总有一天会碰到这样一个需求:微信或QQ对话框里传过来一个文件,用户点开文件,再按右上角“其他应用打开”,列表里能出现自己的App;点进去之后,App还要把文件接收到私有目录里,继续做解析、预览或上传。这里绕不开两个核心关键词: intent-filter 和 文件路径 。真正把这个需求跑通之后我才发现,最折磨人的不是让App出现在列表里,而是拿到那个 content:// URI 之后,怎么安全地把文件落成本地文件。

这篇文章我会从清单配置、FileProvider、ContentResolver 处理、Activity 复用,再到微信/QQ 实测中踩过的坑,完整过一遍。如果你正在做接收外部文件的功能,可以直接照着往下抄。

1. 先搞明白匹配机制:微信/QQ的“打开方式”是怎么选应用的

1.1 一个文件两种入口:ACTION_VIEW 与 ACTION_SEND

用户从微信、QQ里把文件打开时,系统实际投递的隐式 Intent 并不总是一样的。最常见的两个 Action 需要分清:

  • ACTION_VIEW :表示“查看文件”。用户点文件预览、再点“其他应用打开”,大多数时候走的是这个。
  • ACTION_SEND / ACTION_SEND_MULTIPLE :表示“分享文件”。文件消息底部选“发送给朋友”,或者从系统相册点分享,走的是这个。

很多项目只给接收文件的那个 Activity 配了 ACTION_VIEW ,结果QQ里走“分享”入口时,列表找不到自己的应用。我习惯的做法是三个 Action 全部声明,文件接收页面通吃。用户通过哪个入口进来的都能处理,大不了在后面根据 Intent 的 Action 区分一下。

1.2 隐式 Intent 匹配三要素:Action、Category、Data

Android 的系统分发器在决定“哪些应用可以出现在打开列表”时,会拿隐式 Intent 去和所有 App 的 <intent-filter> 匹配,核心看三样东西:Action 是否一致、Category 是否一致、Data(scheme + host + path + mimeType)是否匹配。

  • Action:要能匹配 VIEW / SEND / SEND_MULTIPLE 。
  • Category:必须包含 android.intent.category.DEFAULT ,否则隐式 Intent 不会把 Activity 当成候选。少数会加 BROWSABLE ,但接收文件时通常不需要。
  • Data:微信/QQ 和系统文件选择器传出来的基本都是 content:// URI,MIME 类型按文件实际类型自动识别。想做到“什么文件都能收”,就直接写 scheme="content" + mimeType="*/*" ,再顺带兼容一下文件时代的 file:// 。

另外有一个容易被忽略的点:接收外部 App 的 Intent,Activity 必须设置 android:exported="true" 。Android 12 之后如果带 Intent-Filter 的 Activity 没有显式声明 exported,会直接在安装时崩溃。这个我后面会再说。

2. 清单文件配置:把 Activity 变成一个“文件接收器”

2.1 manifest 里必须写的 Activity 和 Intent-Filter

以 FileReceiveActivity 为例,完整声明如下:

<activity
    android:name=".activity.FileReceiveActivity"
    android:exported="true"
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:theme="@style/Theme.FileReceive">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="content" />
        <data android:scheme="file" />
        <data android:mimeType="*/*" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="*/*" />
    </intent-filter>

    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mime

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_33462167/article/details/165913047

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--