Intent Filters大揭秘

本文深入讲解Android中的Intent机制,包括Intent的基本概念、如何通过Intent启动Activity和服务,以及Intent过滤器的作用。此外,还介绍了Intent中Action、Category和Data的具体用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Intent

Intent:执行的操作以及用于这个操作的数据和其它属性,相当于网页中的url。如下图所示,在打开一个应用的时候,Intent是作为一个重要的数据载体的。

这里写图片描述

下面来看看 Android OS 如何根据 Intent 来找到满足触发条件的 Activity,Service 或是Broadcast Receiver. 借用 SQL 数据库的概念可以更好的理解。

SELECT (Activitives|Services|Broadcast Receivers) AS Target FROM (List in AndroidManifest.xml) WHERE Intent Meet Target’s (Intent Filter)
  • 从 AndroidManifest.xml 中定义的 Activities,Services 和 Broadcast Receiver 列表中查找符合 Intent 条件的 Activities,Services,或是 Broadcast Receivers

  • 所有能活被激活的 Activity,Service 和 Broadcast Receiver 都必须在 AndroidManifest.xml,否则 Android OS 无法查询到该目标,相当于数据库中无记录,即使你在代码中定义了该Activity,Service 或 Broadcast Receiver

开启一个Activity的流程:

(1)Intent intent = new Intent();
(2)intent.setAction("....");
(3)intent.addCategory("....");
(4)intent.setData(Uri.parse("...."));//设置data的scheme、host、path条件
(5)intent.setDataAndType(Uri.parse(""),String type);//同时设置data的scheme、host、path、type条件
(6)startActivity(intent);

priority

网上很多文章中都写到这样一种方法,提高service的优先级别可以用Android:priority = “1000” 的方式来提供servie 的存活时间。其实这是一种没有效果的做法

google文档是这样解释的:链接
1. 优先级的概念用于描述控件的 intent的filter的类型。 这个属性只对activity 和 receivers 是有意义的。
2. 隐式调用activity的情况下: 如果多个activity 满足响应 的条件, 系统只会触发 priority 高的那个activity。
3. 有序广播发出的情况下:如果多个receiver满足响应的条件,系统会优先触发prioriyt搞的那个receiver。
4. priority 必须是整数,默认是0 范围是[-1000, 1000], 默认为0,值越大优先级越高

action

来指定响应的动作名。动作名必须是独一无二的字符串,一个好的习惯是使用基于 Java 包的命名方式的命名系统。最常见的就是:

<action android:name="android.intent.action.MAIN"/>

这里写图片描述

这里写图片描述
我们也可以自定义Action,比如com.flysnow.intent.ACTION_ADD,定义Action的时候最好能表明意思,
要做什么,这样我们的Intent中的数据才好填充。
Intent对象的getAction()可以获取动作,使用setAction()可以设置动作

使用隐式Intent出现android.content.ActivityNotFoundException: No Activity found to handle Intent


Category

Category指定了用于处理Intent的组件的类型信息

<category android:name="android.intent.category.DEFAULT"/> <!--此句一般都要加 -->

最常见的:

<category android:name="android.intent.category.LAUNCHER"/>

一个Intent可以添加多个Category,使用addCategory()方法即可,使用removeCategory()删除一个已经添加的类别。Android的Intent类里定义了很多常用的类别,可以参考使用。

这里写图片描述


Data

Data,其实就是一个URI,用于执行一个Action时所用到的数据的URI和MIME。

不同的Action有不同的数据规格,比如ACTION_EDIT动作,数据就可以能包含一个用于编辑文档的URI,如果是一个ACTION_CALL动作,那么数据就是一个包含了tel:6546541的数据字段,所以上面提到的自定义Action时要规范命名。数据的URI和类型对于Intent的匹配是很重要的,Android往往根据数据的URI和MIME找到能处理该Intent的最佳目标组件。


每个data定义一个URI和数据类型(MIME),URI由4个属性来定义,分别是android:scheme,android:host,android:port,android:path.这个四个属性构成如下格式的URI: scheme://host:port/path 如:content://com.flysnow.intent:8080/show/view。其中content就是scheme,com.flysnow.intent就是host,8080就是port,show/view就是path…如果有经常使用ContentProvider的应该熟悉。。我们经常定义的authority不就是host+port吗?还有这几个元素都是可选的,但是不是随便用就可以的,port要依赖于host,没有host,port就会被忽略,不起作用,同样,如果要使用host+port(authority)就必须指定scheme。而path则依赖于scheme和authority。。

还有一个很重要的类型就是mimeType,这个属性用于指定内容的类型,也就是这个组件可以处理哪些类型的内容。。如text/plain表示无格式文本类型,mimeType也支持通配符,使用text/*则表示所有文本类型。通过使用它,你可以很方便的开发出关联打开诸如txt文件,pdf文件的应用。后面的两个自理将会演示txt文件查看器,图片查看器的例子。。MIME可以参考http://www.w3school.com.cn/media/media_mimeref.asp。这里有所有的内容类型的定义。

注意:

情况1:
<data
android:host="www.xiazdong.com"
android:scheme="xiazdong"/>

intent.setData(Uri.parse("xiazdong://www.xiazdong.com/xia"));

情况2:

在<data>中多了一个android:mimeType="text/*",此时不能使用intent.setData,而要使用intent.setDataAndType();

<data
android:host="www.xiazdong.com"
android:scheme="xiazdong" android:mimeType="text/*"/>

- intent.setDataAndType(Uri.parse("xiazdong://www.xiazdong.com/xia"), "text/plain"); //匹配了text/*

注意的点

  • Action一般设置一个,Category可以设置多个。
  • 使用隐式Intent必须要加上,打开的时候不用add,因为每个Intent默认加上了
<category android:name="android.intent.category.DEFAULT"/>

例子

一、

xml定义:

        <activity android:name=".PackageManagerDemo.PackagerManagerActivity">
            <intent-filter android:priority="0">
                <action android:name="com.bourne.ACTION_PACKAGEMANAGER"/>
                <category android:name="android.intent.category.DEFAULT"/>    <!--此句一般都要加 -->
                <category android:name="com.bourne.CATEGORY_PACKAGEMANAGER"></category>
                <data
                    android:host="www.xiazdong.com"
                    android:mimeType="text/plain"
                    android:scheme="xiazdong">
                </data>
            </intent-filter>
        </activity>

启动Activity:

    public void onClickAction(View view) {
        String ACTION_PACKAGEMANAGER="com.bourne.ACTION_PACKAGEMANAGER";
        String CATEGORY_PACKAGEMANAGER="com.bourne.CATEGORY_PACKAGEMANAGER";

        Intent intent = new Intent();
        intent.setAction(ACTION_PACKAGEMANAGER);
        intent.addCategory(CATEGORY_PACKAGEMANAGER);
        intent.setDataAndType(Uri.parse("xiazdong://www.xiazdong.com/xia"), "text/plain");  //匹配了text/*

        startActivity(intent);
    }

被打开的Activity:

        //获取该Activity对应的Intent的Action属性
        String action=getIntent().getAction();
        //显示Action属性
        Logout.e("Action为:"+action);
        //获取该Activity对应的Intent的Category
        Set<String> cates=getIntent().getCategories();
        //显示Category属性
        Logout.e("Category属性为:"+cates);

效果:
这里写图片描述

二、

Uri、setAction、setData通过按钮启动其他程序:

<uses-permission android:name="android.permission.CALL_PHONE"/>

    //通过隐式意图启动其他程序
    private void btn2Click()//浏览某个网页
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        Uri data = Uri.parse("http://www.163.com");
        intent.setData(data);
        startActivity(intent);
    }
    private void btn1Click()//通过按钮启动拨号
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_CALL);//自动拨号需要设置权限,CALL_PHONE

        //intent.setAction(Intent.ACTION_DIAL);//跳转到拨号界面
        //Uri.fromFile(file)打开某个文件
        Uri data = Uri.parse("tel:110");//号码的uri标示符格式
        intent.setData(data);
        startActivity(intent);
    }

打开另外一个项目:

        Uri data = Uri.parse("http://www.163.com/note");
        intent.setDataAndType(data, "mnt/png");
        startActivity(intent);
            <intent-filter>
                <action android:name="com.example.aex60" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="http" android:host="www.163.com" android:path="/note"
                    android:mimeType="mnt/png"/>
            </intent-filter>

三、打电话

Android APP 两种用程序拨号的方式

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class CallActivity extends Activity {

    private EditText etPhone;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_call);
        etPhone = (EditText) findViewById(R.id.etPhone);
    }

    // ACTION_CALL方式拨打电话(直接拨打)
    public void onClickActionCall(View v) {
        //这里的Intent.ACTION_CALL实际就是一个特定的字符串,
        //ACTION_CALL = "android.intent.action.CALL",
        //告诉系统我要直接拨号了。
        call(Intent.ACTION_CALL);
    }

    // ACTION_DIAL方式拨打电话(打开拨号界面)
    public void onClickActionDial(View v) {
        //同理,这里的Intent.ACTION_DIAL也是一个特定的字符串
        //ACTION_DIAL = "android.intent.action.DIAL"
        //告诉系统我要打开拨号界面,并把要拨的号显示在拨号界面上,由用户决定是否要拨打。
        call(Intent.ACTION_DIAL);
    }

    private void call(String action){
        String phone = etPhone.getText().toString();
        if(phone!=null&&phone.trim().length()>0){
        //这里"tel:"+电话号码 是固定格式,系统一看是以"tel:"开头的,就知道后面应该是电话号码。
        Intent intent = new Intent(action, Uri.parse("tel:" + phone.trim()));
        startActivity(intent);//调用上面这个intent实现拨号
        }else{
            Toast.makeText(this, "电话号码不能为空", Toast.LENGTH_LONG).show();
        }
    }
}

这里写图片描述


参考文章:

Android中Intent的setData,setType和setDataAndType的区别

Android:通过意图启动其他程序、Uri、setAction、setData、setDataAndType

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值