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中需要打电话的权限

 

layout文件





    

        

你可能感兴趣的:(Android之Intent)