Android之Intent

前言

每个应用程序都有若干个Activity组成,每一个Activity都是一个应用程序与用户进行交互的窗口,呈现不同的交互界面。因为每一个Acticity的任务不一样,所以经常互在各个Activity之间进行跳转,在Android中这个动作是靠Intent来完成的。你通过startActivity()方法发送一个Intent给系统,系统会根据这个Intent帮助你找到对应的Activity,即使这个Activity在其他的应用中,也可以用这种方法启动它。

Intent的定义

Intent意图可以是明确的指定组件(四大组件)的名称,这样你可以精确的启动某个系统组件,比如启动一个Activity。它也可以是模糊的,没有指定组件名称,只要是能够匹配到这个Intent的应用都可以接收到,比如发送一个拍照Intent,所有的拍照应用都会响应。

显式Intent和隐式Intent

  1. 显式的Intent就是你已经知道要启动的组件名称,比如某个Activity的包名和类名,在Intent中明确的指定了这个组件(Activity),一般来说这种Intent经常用在一个应用中,因为你已经明确的知道要启动的组件名称。

    当你创建一个显式Intent来启动一个Activity或者Service时,系统会立刻通过你的Intent对象启动那个组件。

  2. 隐式的Intent就是你不知道要启动的组件名称,只知道一个Intent动作要执行,比如:拍照,录像,查看地图。一般来说这种Intent用在不同的应用之间传递信息。

    当你创建一个隐式Intent,系统会根据manifest file中的intent filter找匹配的组件,如果你发送的Intent匹配到一个intent filter,系统会把你的Intent传递给该filter对应的组件(Activity、Service等),并且启动它。如果找到多个匹配的intent filter对应的应用程序,则会弹出一个对话框让你选择哪个应用程序接受你的Intent。

注:

  • intent filter是一种应用程序manifest文件中的语法表达,就像是html的标签,它是一个系统组件标签(比如:Activity)的组成部分,可以说是子标签吧,这个系统组件接受什么样的intent就是用它来指定的,如果一个系统组件不写intent filter,那么它只能通过显式的intent来启动。
  • 出于安全的角度,你的Service组件务必不要用隐式的intent filter来进行说明,因为用隐式的intent启动一个Service往往不能保证Service会被启动,并且用户也不知道哪个Service会响应你的Intent。从Android5.0(API 21),系统会抛出异常当你用隐式的Intent去调用bindService()方法。

Intent七大属性

Intent对象大致包括7大属性:ComponentName、 Action 、 Category 、 Data 、Type、 Extra 、Flag。

  • Component Name(目标组件): 目标组件
    要启动的组件名称,在创建Intent的时候是可选的,但是它是显式Intent的重要标志,有它就意味着只有Component name匹配上的那个组件才能接收你发送出来的显示intent。如果不写那么你创建的Intent就是隐式的,系统会根据这个intent的其他信息(比如:action、data、category)来确定哪些组件来接收这个intent,所以如果你想明确的启动哪个组件,就通过component name来指定。

    Intent的ComponentName属性是一个类的全称,包括包名,比如:com.example.ExampleActivity,你可以通过Intent的setComponent(),setClass(),setClassName()方法来设定,也可以通过Intent的构造方法来设定。

  • Action(动作): 用来表示意图的动作,如:查看,发邮件,打电话
    是一个可以指明目标组件行为的字符串。action很大程度上决定了category和data中应传入的信息;您也可以在自己的应用程序组件中指定action,以便让其他应用程序启动自己的组件。对应action中字符串,不建议使用硬编码的形式,而应在所属组件的类中设置为常量。

    如需在自己的组件中定义action,应以应用的包名作为前缀,比如:

    public static final String ACTION_TIMETRAVEL="com.example.action.TIMETRAVEL";
    

    常用动作
    最常用的是Action_MAIN(作为初始的Activity启动,没有数据的输入输出)

     ACTION_MAIN:(android.intent.action.MAIN)Android程序入口。
     每个Android应用必须且只能包含一个此类型的Action声明。【如果设置多个,则哪个在前,执行哪个。】
    ACTION_VIEW: (android.intent.action.VIEW) 显示指定数据。
    ACTION_EDIT: (android.intent.action.EDIT) 编辑指定数据。
    ACTION_DIAL: (android.intent.action.DIAL) 显示拨号面板。
    ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所带的号码。
    ACTION_ANSWER: (android.intent.action.ANSWER) 接听来电。
    ACTION_SEND: (android.intent.action.SEND) 向其他人发送数据(例如:彩信/email)。
    ACTION_SENDTO:  (android.intent.action.SENDTO) 向其他人发送短信。
    ACTION_SEARCH: (android.intent.action.SEARCH) 执行搜索。
    ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 让用户选择数据,并返回所选数据。
    

    setAction(String action) 用来设置Intent的动作,参数可以为常量
    getAction() 方法用来获取Intent动作名称
    上面的Action都是系统定义好的,具有一定意义的动作指向的动作。
    Intent的Action对象其实就是一个字符串常量,系统的Action对象是系统定义好的字符串常量,我们也可以自己定义自己的Action作为字符串常量。就像上面的例子使用到了自定义的Action字符串对象。

  • category(类别): 用来表示动作的类别。
    Intent的action、category属性都是普通的字符串,其中action表示Intent需要完成的一个抽象”动作”,而category则为action添加额外的类别信息,通常action和category一块使用。
    需要指出的是,一个Intent中只能包含一个action属性,但可以包含多个category属性。当程序创建Intent时,该Intent默认启动常量值为andorid.intent.category.DEFAULT的组件。这里的一个Intent中只能包含一个action属性,并不是Activity中xml的设置规范,而是你要跳转到的页面去,你只能设置一个Action的值。
    常用的Category:

    CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。 
    CATEGORY_HOME:设置该组件为Home Activity。
    CATEGORY_PREFERENCE:设置该组件为Preference。 
    CATEGORY_LAUNCHER:设置为当前应用程序优先级最高的Activity,通常与ACTION_MAIN配合使 用。 
    CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。 
    CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。

  • data(数据): 表示与动作要操作的数据。如:查看指定的联系人
    Data数据用来向Action属性提供动作的数据。这里的Data不是Intent里面的数据,而是指明动作的具体数据,比如说动作是打电话,那么打给具体的某一个人,就用到了date里面的数据来指定。同样发邮件、或打开具体的某一个网址也是通过Data数据。
    Data属性只接受Uri对象,Uri对象是统一资源标识符。对应概念不用太多理解,只需知道里面某些具体值的表现形式就可以了。
    Uri其实就是相当于一个网址,如图所示:
    网址只是Uri其中一种格式的字符串,要使用它还要把它解析后转化为Uri类型。
    为Intent对象添加Data数据,代码:
    intent.setData(Uri.parse(“http://www.baidu.com“));

    系统内置的几个Data属性常量:

    tel://:号码数据格式,后跟电话号码。
    mailto://:邮件数据格式,后跟邮件收件人地址。
    smsto://:短息数据格式,后跟短信接收号码。
    content://:内容数据格式,后跟需要读取的内容。
    file://:文件数据格式,后跟文件路径。
    market://search?q=pname:pkgname:市场数据格式,在Google Market里搜索包名为pkgname的应用。
    geo://latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
    
  • type(数据类型): 对data类型的描述。
    与Data有关的,这个不是Intent的数据类型,是Intent的Action的Data数据的类型

    intent.setAction(android.content.Intent.ACTION_VIEW);
    Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4");
    String type = "video/mp4";
    intent.setDataAndType(uri,type);
    startActivity(intent)
    
  • extras(附件信息): 附件信息。如:详细资料,一个文件,某事。
    extras属性主要用于传递目标组件所需要的额外的数据。
    通过putExtras()方法设置。保存数据;
    通过getExtras()方法设置。获取数据

    通常我们使用Intent来直接传递Bundle对象,但也可以传递其他系统内置的一些参数。
    如果要传递是是对象,那么对象必须实现序列化。

    Intent intent = new Intent();
    intent.setClass(this, SubActivity.class);
    // 直接添加
    //intent.putExtra("MyData", new ParcelableData());
    // 通过Bundle
    Bundle bundle = new Bundle();
    bundle.putString("MyString", "test bundle");
    bundle.putParcelable("MyData", new ParcelableData());
    intent.putExtras(bundle);
    startActivity(intent);
    
    //ParcelableData parcelableData = getIntent().getParcelableExtra("MyData");
    Bundle bundle = getIntent().getExtras();
    ParcelableData parcelableData = bundle.getParcelable("MyData");
    String testBundleString = bundle.getString("MyString");
    Log.v("string=", testBundleString);
    Log.v("name=", parcelableData.getName());
    Log.v("age=", ""+parcelableData.getAge()); 
    
  • flags属性:Intent可调用addFlags()方法来为Intent添加控制标记。

    1、FLAG_ACTIVITY_CLEAR_TOP:(效果同Activity LaunchMode的singleTask)

    2、FLAG_ACTIVITY_SINGLE_TOP:(效果同Activity LaunchMode的singleTop)

    3、FLAG_ACTIVITY_NEW_TASK: (效果类似Activity LaunchMode的singleInstance)

捉到一只Sample↓↓↓↓↓

MianActivity.java


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//从Android 7.0开始,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException。
//解决方法置入一个不设防的VmPolicy,但是要确保目标应用有本地读写权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }

    }
    public void clickButton(View view) {

        Intent intent = new Intent();

        intent.setAction(android.content.Intent.ACTION_VIEW);



        switch (view.getId()) {

            case R.id.button_main_call:

                intent.setAction(Intent.ACTION_CALL);

                intent.setData(Uri.parse("tel:10086"));

                break;

            case R.id.button_main_dial:

                intent.setAction(Intent.ACTION_DIAL);

                intent.setData(Uri.parse("tel:10086"));

                break;

            case R.id.button_main_dialer:

                intent.setAction("com.android.phone.action.TOUCH_DIALER");

                break;

            case R.id.button_main_sms:

                intent.setAction(Intent.ACTION_SENDTO);

                intent.setData(Uri.parse("smsto:10086"));
                intent.putExtra("sms_body", "该吃饭了,下课吧!");

                break;

            case R.id.button_main_setting:

                intent.setAction("android.settings.SETTINGS");

                break;

            case R.id.button_main_datesetting:

                intent.setAction("android.settings.DATE_SETTINGS");

                break;

            case R.id.button_main_soundsetting:

                intent.setAction("android.settings.SOUND_SETTINGS");

                break;

            case R.id.button_main_wifisetting:

                intent.setAction("android.settings.WIFI_SETTINGS");

                break;

            case R.id.button_main_contacts:

                intent.setAction("com.android.contacts.action.LIST_CONTACTS");

                break;

            case R.id.button_main_web:

                intent.setAction(android.content.Intent.ACTION_VIEW);

                intent.setData(Uri.parse("http://www.baidu.com"));

                break;

            case R.id.button_main_showimage:

                intent.setAction(android.content.Intent.ACTION_VIEW);

                intent.setDataAndType(

                        Uri.fromFile(new File("mnt/sdcard/Download/landscape.jpg")),

                        "image/*");

                break;

            case R.id.button_main_showtext:

                intent.setAction(android.content.Intent.ACTION_VIEW);

                intent.setDataAndType(

                        Uri.fromFile(new File("mnt/sdcard/Download/info.txt")),

                        "text/*");

                break;

            case R.id.button_main_playaudio:

                intent.setAction(android.content.Intent.ACTION_VIEW);

                intent.setDataAndType(Uri.fromFile(new File(

                        "mnt/sdcard/Download/heavencity.mp3")), "audio/*");

                break;

            case R.id.button_main_playvideo:

                intent.setAction(android.content.Intent.ACTION_VIEW);
                String type = "video/mp4";
                Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4");

                intent.setDataAndType(uri,type);

                break;

            case R.id.button_main_home:

                intent.setAction("android.intent.action.MAIN");

                intent.addCategory("android.intent.category.HOME");

                break;

            default:

                break;

        }

        startActivity(intent);

    }
}

AndroidManifest.xml中需要打电话的权限

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

layout文件

<?xml version="1.0" encoding="utf-8"?>
<ScrollView

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/scrollView1"

    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical">

        <Button

            android:id="@+id/button_main_call"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="直接拨号" />


        <Button

            android:id="@+id/button_main_dial"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="启动拨号面板" />


        <Button

            android:id="@+id/button_main_dialer"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="显示拨号面板" />


        <Button

            android:id="@+id/button_main_sms"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="发送短信" />


        <Button

            android:id="@+id/button_main_setting"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="系统设置" />

        <Button

            android:id="@+id/button_main_datesetting"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="日期设置" />

        <Button

            android:id="@+id/button_main_soundsetting"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="声音设置" />

        <Button

            android:id="@+id/button_main_wifisetting"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="WIFI设置" />

        <Button

            android:id="@+id/button_main_web"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="浏览网页" />

        <Button

            android:id="@+id/button_main_contacts"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="查看联系人" />

        <Button

            android:id="@+id/button_main_showimage"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="查看图片" />

        <Button

            android:id="@+id/button_main_showtext"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="查看文本" />

        <Button

            android:id="@+id/button_main_playvideo"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="播放视频" />

        <Button

            android:id="@+id/button_main_playaudio"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="播放音频" />

        <Button

            android:id="@+id/button_main_home"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="clickButton"

            android:text="HOME" />


    </LinearLayout>

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

推荐阅读更多精彩内容