认识Intent

Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务、以及发送广告等场景。

Intent的用法分为显式Intent和隐式Intent两种。接下来详细解析。

1.了解Intent的构造方法

Intent的方法有很多,通过认识构造方法,我们能够窥探到Intent的不同用法。

1.空构造方法:

    public Intent() {
    }

2.根据另一个Intent创建的构造方法

    public Intent(Intent o) {
        this.mAction = o.mAction;
        this.mData = o.mData;
        this.mType = o.mType;
        this.mPackage = o.mPackage;
        this.mComponent = o.mComponent;
        this.mFlags = o.mFlags;
        this.mContentUserHint = o.mContentUserHint;
        if (o.mCategories != null) {
            this.mCategories = new ArraySet<String>(o.mCategories);
        }
        if (o.mExtras != null) {
            this.mExtras = new Bundle(o.mExtras);
        }
        if (o.mSourceBounds != null) {
            this.mSourceBounds = new Rect(o.mSourceBounds);
        }
        if (o.mSelector != null) {
            this.mSelector = new Intent(o.mSelector);
        }
        if (o.mClipData != null) {
            this.mClipData = new ClipData(o.mClipData);
        }
    }

3.由一条Action创建的构造方法

    public Intent(String action) {
        setAction(action);
    }

其中的setAction()方法如下:

    public Intent setAction(String action) {
        mAction = action != null ? action.intern() : null;
        return this;
    }

4.通过Action和Uri共同创建的构造方法

    public Intent(String action, Uri uri) {
        setAction(action);
        mData = uri;
    }

5.通过Context和Class文件创建的构造方法

    public Intent(Context packageContext, Class<?> cls) {
        mComponent = new ComponentName(packageContext, cls);
    }

6.大杂烩,通过Action、Uri、Context还有Class文件创建的构造方法

    public Intent(String action, Uri uri,
            Context packageContext, Class<?> cls) {
        setAction(action);
        mData = uri;
        mComponent = new ComponentName(packageContext, cls);
    }

通过这些构造方法,我们需要从中学习到,不同构造方法的Intent,其作用是不同的。

1.参数要求为Context以及Class的

接下来会在构造方法中会创建出ComponentName对象,这个是Android的组件,是可以具体到某个具体的组件的,这种就是显式的使用方法。

2.参数要求为Action的

接下来会在构造方法中调用setAction()方法,也就是给mAction赋值,对应到AndroidManifest文件中的<intent-filter><action>标签,在启动时,如果配置了相同action和category的Activity都可能被启动起来,如果匹配到多个,会弹出对话框让用户手动选,这种就是隐式的使用方法。

2.隐式使用Intent的注意事项

  • 每个Intent中只能指定一个action,但是可以指定多个category。

  • startActivity()方法中会自动将"android.intent.category.DEFAULT"这个默认的category添加到Intent中,如果被启动的Activity声明的category正好就是默认的话,可以不用写。

  • 在AndroidManifest文件中声明Activity的时候,如果希望这个Activity是用隐式的方式被启动,那么在<intent-filter>标签中,必须要添加上这一条:

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

如果AndroidManifest文件中没有这一条,那么即使Action能够匹配上依然会崩溃。
如下:

           <intent-filter>
               <action android:name="com.company.windmajor.JUMP"/>

               <category android:name="android.intent.category.DEFAULT"/>
           </intent-filter>

代码调用:

                Intent intent = new Intent();
                intent.setAction("com.company.windmajor.JUMP");
                startActivity(intent);
  • 如果有自己限定category的需求,那么可以先添加上面一点中提到的DEFAULT的category,然后再定义自己的category。然后在java代码中添加自己定义的category。如下:
            <intent-filter>
                <action android:name="com.company.windmajor.JUMP"/>

                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="com.company.windmajor.category.JUMP"/>
            </intent-filter>

代码中的调用:

                Intent intent = new Intent();
                intent.setAction("com.company.windmajor.JUMP");
                intent.addCategory("com.company.windmajor.category.JUMP");
                startActivity(intent);

3.更多隐式Intent的用法

使用Intent,还可以启动其他App的Activity,这将使得Android多个应用程序之间的功能共享成为了可能。
这里介绍几个用法:Intent.ACTION_VIEW和Intent.ACTION_DIAL

(1)Intent.ACTION_VIEW

这个Action是系统定义的Action,可以将带有浏览器功能的App给打开,使用代码如下:

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://www.baidu.com"));
                startActivity(intent);
            }
        });

这段代码的效果就是打开浏览器,然后访问百度网。
setData()的方法接受Uri对象,主要用于指定当前Intent正在操作的数据,而这些数据通常都是以字符串的形式传入到Uri.parse()方法中解析产生的。
与此对应,我们还可以在<intnet-filter>标签中再配置一个<data>标签,用于更精确的指定当前活动能够相应什么类型的数据。<data>标签中,主要可以配置以下内容。

  • android:scheme 指定数据的协议部分,如上面代码里的http部分
  • android:host 指定数据的主机名部分,如上面代码里的www.baidu.com部分
  • android:port 指定数据的端口部分,一般紧随在主机名之后
  • android:path 指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容
  • android:mimeType 指定可以处理的数据类型,允许使用通配符的方式进行指定。

只有<data>标签中指定的内容和Intent中携带的Data完全一致是,当前Activity才能响应该Intent。

那么如何自己创建一个可以响应系统需求的Activity呢?
首先创建一个布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view_two"
        android:text="Activity Two"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

然后创建一个新的Activity:

public class TwoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);

    }
}

最后非常重要的是一定要在AndroidManifest文件中注册新的Activity

        <activity android:name=".TwoActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="http" />
            </intent-filter>
        </activity>

这样运行起来之后,点击刚才的那个按钮,就可以看到选择启动程序的一个列表,列表中包括浏览器还包括我们刚刚创建新Activity的这个程序。当然只有打开浏览器,我们才能看到百度网页面的各种广告,点击我们自己的程序是不能看到的,因为我们的程序也没有写处理浏览登陆的代码。

(1).Intent.ACTION_DIAL

使用代码如下:

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

4.Activity之间的数据互传

Intent可以用来启动Activity,当然也是可以传递数据的,为了方便Activity之间的数据通信,Activity提供了putExtra()方法的重载,可以传递许多中类型的数据。
使用代码如下:

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, TwoActivity.class);
                intent.putExtra("EXTRA_DATA","Hello SecondActivity");
                startActivity(intent);
            }
        });

这里putExtra()方法的第一个参数是“键”,第二个参数是真正的“值”,键通常都是String类型的,值可以有很多种类型。那么这个地方传递了,别的地方如何取呢?

        Intent intent = getIntent();
        String data = intent.getStringExtra("EXTRA_DATA");

只需要在被启动的Activity里面使用如上的代码即可。当然要知道传的时候是什么类型,取的时候必须要能类型匹配上。不然不行。

当上一个Activity传递数据给下一个Activity,那么下一个Activity如何将数据结果传递回给上一个Activity呢?这里需要介绍一下startActivityForResult()方法。
这个方法需要两个参数,第一个参数是启动Intent,第二个参数是启动的请求码,只要是唯一的整型数字即可。

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, TwoActivity.class);
                intent.putExtra("EXTRA_DATA", "Hello SecondActivity");
                startActivityForResult(intent, 1);
            }
        });

当用户在界面TwoActivity完成了相应的操作,得到了想要的数据,需要将这个数据返回给第一个MainActivity,只需要下面这么做:

        twoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("EXTRA_RETURN", "This is the result...");
                setResult(RESULT_OK, intent);
                finish();
            }
        });

我们看到上面的Intent仅仅只是用来传递数据,setResult()方法很重要,第一个参数用于向前一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个系统定义好的值表示成功与失败,第二个参数是把带有数据结果的Intent对象传递回去。最后使用finish()方法将当前的Activity销毁。

由于我们是使用startActivityForResult()方法来启动的第二个Activity,这种启动方法需要实现一个特殊的方法才可以使用第二个Activity返还回来的数据。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returnedData = data.getStringExtra("EXTRA_RETURN");
                    Log.i("MainActivity", returnedData);
                }
                break;
            default:
                break;
        }
    }

这个方法有三个参数,第一个参数requestCode是启动第二个Activity时的启动码,我们设置的是1,第二个参数resultCode是从第二个Activity返还回来时的结果码,一般有两种RESULT_OK和RESULT_CANCELED,第三个参数data就是带着数据的Intent对象。

以上就是Intent的一些简单的特性和使用方法,希望共同勉励。

案例和知识点都来源于郭霖的《第一个行代码》,在此特别感谢郭老师,希望大家看完本篇文章后,希望全面了解的可以购买郭老师的书。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容