嘿,各位Android开发圈的老铁们,今天咱们不聊风花雪月,来唠点实在的——Intent过滤器。这玩意儿,说它是Android应用的“社交名片”一点都不过分。你想啊,你的App要是整天关起门来自己玩,那多没意思?总得和系统、和其他App打打交道吧?比如,优雅地打开一个网页,帅气地分享一张图片,或者低调地处理一个文件。
这时候,你就需要一个“媒人”,也就是我们上回书说到的Intent。但光有媒人还不够,你家“姑娘”(也就是你的Activity、Service等)得有个明确的“征婚启事”吧?告诉媒人:“我想找什么样的对象(Intent),身高(Action)多少,家境(Data)如何,性格(Category)咋样……” 这个“征婚启事”,就是咱们今天的主角——Intent过滤器。
它住在哪里呢?它就安安稳稳地待在你项目的
AndroidManifest.xml 文件里,像一个大家闺秀,大门不出二门不迈。它的标签是
<intent-filter>,通常“寄生”在某个
<activity>、
<service> 或
<receiver> 的体内。
一个标准的“征婚广告”长这样:
<activity android:name=".MyAwesomeActivity">
<intent-filter>
<!-- 我想干啥?—— 行动准则 -->
<action android:name="android.intent.action.VIEW" />
<!-- 我属于哪一类?—— 身份标签 -->
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 我能接受啥条件?—— 数据要求 -->
<data android:scheme="https" />
<data android:host="www.example.com" />
</intent-filter>
</activity>
看到了吗?一个合格的过滤器,通常由三大核心要素构成:Action(行动)、Category(类别)、Data(数据)。咱们来一个个盘它们。
1. Action(行动):你想干啥?
Action就是Intent的“意图”,直接说明了你想执行什么操作。系统定义了一大堆标准的Action,比如:
ACTION_VIEW: 查看内容,最常用的“暖男”型Action。
ACTION_SEND: 发送内容,典型的“分享达人”。
ACTION_EDIT: 编辑内容,专业的“文案编辑”。
ACTION_DIAL: 拨号,通讯界的“老司机”。
你也可以自定义Action,但通常,用系统的就够你“浪”了。
2. Category(类别):你是个啥样的人?
Category给Intent提供了一些额外的“上下文信息”,或者说,描述了目标组件的“性格特征”。最常见的,也是必须的,就是
CATEGORY_DEFAULT。
敲黑板!划重点! 几乎所有通过
startActivity() 发起的隐式Intent,都默认带上了
CATEGORY_DEFAULT 这个标签。所以,如果你的Activity想通过隐式Intent被启动,就必须在它的过滤器里声明这个Category!不然,系统媒人会觉得你“性格不合”,直接Pass掉你。很多新手在这里栽跟头,切记切记!
其他常见的Category还有
CATEGORY_BROWSABLE(允许通过浏览器链接启动)、
CATEGORY_LAUNCHER(表明是启动器Activity,会在桌面显示图标)。
3. Data(数据):你对对象有啥要求?
Data是过滤器里最“矫情”也最强大的部分。它规定了Intent必须携带什么样的数据才能匹配成功。它可以拆解成好几个部分,像一个详细的择偶标准:
android:scheme: URI的协议,比如
http,
https,
content,
file,或者你自定义的
myapp。
android:host: 主机名,比如
www.google.com。
android:port: 端口号。
android:path,
android:pathPrefix,
android:pathPattern: 路径相关,非常精确的匹配。
android:mimeType: 数据的MIME类型,如
image/jpeg,
text/plain。
一个精辟的比喻:你把Data的匹配规则想象成一个URL:
https://www.example.com:8080/images/cat.jpg。
scheme 就是
https
host 就是
www.example.com
port 就是
8080
path 就是
/images/cat.jpg
过滤器可以只指定其中一部分,比如只要求
scheme 是
https,那所有HTTPS链接都能匹配上,是个“海王”。如果所有部分都指定了,那就只匹配那一个特定的URL,是个“情种”。
光说不练假把式,咱们来写一个真实的例子。假设我们要做一个App,里面有一个Activity,专门负责“丧心病狂”地分享文本和图片。
第一步:编写“征婚广告”(修改 AndroidManifest.xml)
<activity android:name=".ShareGhostActivity"
android:label="分享到我的App">
<!-- 过滤器1:处理发送文本 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<!-- 指定数据类型为文本 -->
<data android:mimeType="text/plain" />
</intent-filter>
<!-- 过滤器2:处理发送图片 -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<!-- 指定数据类型为图片 -->
<data android:mimeType="image/*" />
</intent-filter>
<!-- 过滤器3:处理发送多张图片 -->
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
解读一下这份“广告”:
我们这个
ShareGhostActivity 挂了三个“招牌”。第一个招牌说:“我能干
SEND 的活儿,只接
text/plain(纯文本)的单。”第二个招牌说:“我也能干
SEND 的活儿,但这次接所有图片 (
image/*) 的单。”第三个招牌说:“我还能干
SEND_MULTIPLE 的活儿,专门处理多张图片。”
这样,当用户在微信、图库等地方点击“分享”时,我们的App就会出现在分享列表里,成为一个可选项!
第二步:在Activity里“接单”(处理Intent)
光被“看上”还不行,得会“谈恋爱”。我们得在Activity里把Intent送过来的数据处理好。
public class ShareGhostActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share_ghost);
// 1. 拿到“媒人”递过来的Intent
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
// 2. 判断是啥“业务”
if (Intent.ACTION_SEND.equals(action) && type != null) {
// 单条内容分享
handleSendIntent(intent);
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
// 多条内容分享
handleSendMultipleIntent(intent);
} else {
// 啥也不是,可能是被人误点了,直接关闭
finish();
}
}
private void handleSendIntent(Intent intent) {
// 获取Intent里附带的“数据”
if ("text/plain".equals(intent.getType())) {
// 处理文本
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
// 显示文本,比如放到一个TextView里
TextView textView = findViewById(R.id.shared_text_view);
textView.setText("分享来的文本:" + sharedText);
// 这里你可以进一步处理,比如发布到你的服务器
}
} else if (intent.getType().startsWith("image/")) {
// 处理单张图片
Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
// 显示图片,可以用Glide, Picasso等库
ImageView imageView = findViewById(R.id.shared_image_view);
imageView.setImageURI(imageUri);
// 这里你可以上传图片等等
}
}
}
private void handleSendMultipleIntent(Intent intent) {
// 处理多张图片
ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (imageUris != null && !imageUris.isEmpty()) {
// 恭喜你,拿到了一堆图片Uri,可以批量处理了
for (Uri uri : imageUris) {
// 遍历处理每一张图片
Log.d("ShareGhost", "收到图片: " + uri.toString());
}
}
}
}
看,逻辑很清晰吧?先判断Action和Type,然后根据不同的类型,从Intent的Extras里取出对应的数据。文本就用
EXTRA_TEXT,单个文件流用
EXTRA_STREAM,多个文件流用
EXTRA_STREAM 的ArrayList。
Intent.createChooser() 方法来创建一个选择器。
Intent shareIntent = new Intent(Intent.ACTION_SEND);
// ... 设置intent的其他属性
Intent chooser = Intent.createChooser(shareIntent, "分享到...");
startActivity(chooser);
先查户口再“提亲”(检查是否有App能处理):
PackageManager 的
resolveActivity() 方法查一下,看看有没有App能接这个活。如果没有,你还强行发送,App就会崩溃。
if (shareIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
} else {
Toast.makeText(this, "没有找到可以处理分享的应用", Toast.LENGTH_SHORT).show();
}
“征婚广告”不是越多越好:好了,关于Android界的“红娘”Intent和它的“征婚广告”过滤器,咱们就聊到这里。现在你是不是觉得,它不再是冷冰冰的配置代码,而是一个活生生的、帮你拓展App社交圈的利器了?
记住核心心法:Action定方向,Category定身份,Data定细节。三大要素,缺一不可,共同为你App的组件们铺平了通往“星辰大海”的道路。
赶紧打开你的Android Studio,给你的App组件们写一份漂亮的“征婚广告”,让它们在系统的应用生态里,成为最靓的仔吧!