基础

Intent详细解释

Intent详细解释

Intent是一种意图,用于启动Activity、Service、BroadcastReceiver

类型 方法
Activity startActivity(Intent intent)
startActivityForResult(Intent intent, int requestCode)
Service ComponentName startService(Intent service)
boolean bindService(Intent service, ServiceConnection conn, int flags)
BroadcastReceiver sendBroadcast(Intent intent)
sendOrderedBroadcast(Intent intent, String receiverPermission)

右侧的方法都是在Context中(除了startActivityForResult),而且Activity和Service都是Context的子类,就是在Activity和Service中都能启动三大组件

Intent有7个属性:Action、Category、Data、Type、Extra、Flag、Compontent

Intent有两种启动方式:显示启动(指定找XXX)、隐式启动(指定条件,比如是一个大美女)

七大属性

Compontent

适用于显示启动,表示来源(就是上下文参数)和启动的目的地(要启动的组件)

三个构造函数:

ComponentName(String pkg, String cls)

ComponentName(Context pkg, String cls)

ComponentName(Context pkg, Class<?> cls)

启动另外一个App中的Activity

第一个可以用来启动第二个APP中的Activity:

        //指定另外一个APP的包名和类名
        ComponentName name = new ComponentName("win.haotinayi.animator", "win.haotinayi.animator.MainActivity");
        Intent intent = new Intent();
        intent.setComponent(name);
        startActivity(intent);

注意第二个参数要写全名,这样可以启动包名是win.haotinayi.animator中的MianActivity

启动本App中的Activity

指定上下文和对应的组件名:

        ComponentName name = new ComponentName(MainActivity.this, "win.haotinayi.intent.Main2Activity");
//两种方法一个是直接写出全名,一个是写出class
//        ComponentName name = new ComponentName(MainActivity.this, Main2Activity.class);
        Intent intent = new Intent();
        intent.setComponent(name);
        startActivity(intent);

简化写法

可以在构造Intent的时候直接写出上下文和类名(只适用显示启动)

        Intent intent = new Intent(MainActivity.this, Main2Activity.class);
        startActivity(intent);

Category和Action

Action表示一个具体的动作,Categoey是Action增加的额外信息。在隐式启动中要给三个组件添加<intent-filter>子标签而intent-filter子标签可以有action、category、data。Data和Type属性都在data标签内。

即使没有指定特定的Category系统会默认添加一个<category android:name=”android.intent.category.DEFAULT”/>的标签。

在intent-filter中可以有多个action和category,但是最多只能有一个data标签,action和category的本质就是一个字符串,用name属性表示,比如主启动Activity:

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
​
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

隐式启动

启动Mian3Activity的代码:

        Intent intent = new Intent();
        intent.setAction("haotianyi.win");
        startActivity(intent);
        <activity android:name=".Main3Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
            </intent-filter>
        </activity>

这时会报错:

这是因为系统默认会给intent添加值是android.intent.category.DEFAULT的category,更改注册文件,可以启动

        <activity android:name=".Main3Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

当两个Activity的注册文件当Action相同,但是category不同,那么只要action和intent匹配就可以启动,AndroidManifest文件:

        <activity android:name=".Main3Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
        <!--只是多了一个值是“你妹的”category属性-->
        <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <category android:name="nimeide"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

Activity的启动代码:

        Intent intent = new Intent();
        intent.setAction("haotianyi.win");
        startActivity(intent);

这时候系统会弹出让你选择那一个Activity:

从Intent中获得信息

在Mian2Activity中添加代码,获得当前的ComponentName、Action和Category

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
​
        ComponentName component = getIntent().getComponent();
        System.out.println(component.getClassName());
        System.out.println(component.getPackageName());
​
        System.out.println(getIntent().getAction());
​
        Set<String> categories = getIntent().getCategories();
//      假如用for循环的话会报错,因为值是null
//      这里的Categeory是Intent携带的而不是Activity注册的Intent
        System.out.println(categories);
    }

从借助Intent从目标组件返回信息

可以借助Intent从一个组件发送信息到另一个组件(处理信息),另外一个组件返回处理后的值,这样的情景可以使用onActivityForResult方法

启动Activity,第二个参数起到一个标识的作用(从哪里来)

        Intent intent = new Intent();
        intent.setAction("haotianyi.win");
        startActivityForResult(intent,0);

在第二个Activity中,设置结果,setResult参数也起到表示作用(处理结果怎么样)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        setResult(1);
    }

但第二个Activity处理完成并且被finish掉,第一个Activity会回调onActivityForResult方法

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

返回桌面

设置Action和Category标签即可

        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        startActivity(intent);

Extra

Intent额外携带的数据,用putXXX来携带各种类型的数据,用getXXXX来获得数据,更改上面的案例,Activty1的发送代码:

        Intent intent = new Intent();
        intent.putExtra("hello","你好啊");
        intent.setAction("haotianyi.win");
        startActivityForResult(intent,0);

Activity2的处理代码,就是给原有数据添加一句话

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        String hello = getIntent().getStringExtra("hello");
        hello += "-----这时来自Activity2的问候";
        Intent result = getIntent().putExtra("hello", hello);
//      打印Activity2正在处理
        System.out.println(getLocalClassName()+"正在处理数据-------"+hello);
        setResult(1,result);
    }

Activity1的回调代码

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode,resultCode,data);
//      打印结果码
        System.out.println(resultCode);
//      打印处理之后的结果
        System.out.println(getLocalClassName()+"处理之后的数据是------"+data.getStringExtra("hello"));
    }

Data和Type

Intent的Data属性是执行动作的URI和MIME类型,不同的Action有不同的Data数据指定。比如:ACTION_EDIT Action应该和要编辑的文档URI Data匹配,ACTION_VIEW应用应该和要显示的URI匹配。

Intent的Type属性显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行判定。只要Type负责abc/xyz格式的字符串都可以。

Data和Type在单独指定的时候会相互覆盖,同时指定来两个值使用:setDataAndType方法

Data的匹配规则

Data的参数类型是Uri,例如content://win.hao.ty/data/1

Uri对应的名称是scheme://host/path 三个部分,在host后面可能有port相当于端口号

scheme、host、path是一个范围递减的三个属性(从大到小),就是某一个注册Activity只是指定了scheme属性,那么所有的Intent的Data属性只要以对应字段开头都会匹配

具体匹配实例

有这样三个Activity

       <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <data android:scheme="hao"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
​
        <activity android:name=".Main3Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <data android:scheme="hao" android:host="tianyi"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
​
        <activity android:name=".Main4Activity">
            <intent-filter>
                <action android:name="haotianyi.win"/>
                <data android:scheme="hao" android:host="tianyi" android:path="/datas/1"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

对应的Intent如下,分别注释掉不同的赋值语句在启动的时候就会打开几个Activity

        Intent intent = new Intent("haotianyi.win");
//       只是启动一个Activity
        intent.setData(Uri.parse("hao://"));
//      启动了两个Activity
        intent.setData(Uri.parse("hao://tianyi"));
//       启动了三个Activity
        intent.setData(Uri.parse("hao://tianyi/datas/1"));
        startActivity(intent);

发表评论

电子邮件地址不会被公开。