Intent相关

一、定义

消息传递的对象,可以用来从其他应用组件请求操作,基本用例如下:

  • 启动Activity
  1. startActivity() 启动新的activity,其中intent可以携带相应的数据,但是携带数据必须可序列化,String和基本数据类型。同时数据携带有大小限制,具体限制大小可以查看该网址

      Intent intent = new Intent(MainActivity.this, SecondActivity.class);
      startActivity(intent);
    
  1. startActivityForResult() 启动新的Acitivity并在新页面返回时候,可携带部分数据返回。注意①如果跳转前页面为fragment,必须重写它依赖的Activity或者父类fragment,否则会出现接收不了情况 ②如果所在fragment在viewpager下,不仅应该重写Acitity,而且应该区别处理回调处理,防止所有fragment收到相关回调。

       Intent intent = new Intent(this, SecondActivity.class);
       startActivityForResult(intent, REQUEST_CODE);
    
  • 启动服务
  1. 对于API 21之前的版本,可以用intent.startService()来启动服务
  2. 服务旨在使用客户端-服务端接口,通过bindService()将intent传递
  • 传递广播

    启动广播,sendBroadCast()或者sendOrderBroadCast()将intent传递给广播接收者

二、Intent类型

1.显示调用

​ 通过目标的包名称或者组件名称,启动相应组件。

        //  使用构造函数,传入context,class
//       Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        Intent intent = new Intent();
        //使用className来
        intent.setClassName(MainActivity.this, "com.yobin.testintent.SecondActivity");
        startActivity(intent);
2.隐式调用

不会指定特定的组件,只是声明常规操作,从而允许其他应用中的组件来处理

三、构建Intent

  • action

    指定要执行的通用操作的字符串,很大程度决定其余Intent的构成,特别是数据和extra中包含的内容。通常的操作常量ACTION_VIEW(向用户显示信息), ACTION_SEND(向用户共享数据)

  • data

  • type

    data是Uri类型数据,type是数据MIME类型,指定数据的MIME类型数据有助于Android系统找到接收Intent的最佳组件

    注意:调用setData和调用setType不能同时调用,因为会互相抵消彼此的值,如果需要设置用setDataAndType()同时设置URI和MIME类型

     private String getMIMEType(File file) {
    
            String type = "*/*";
            String fName = file.getName();
            // 获取后缀名前的分隔符"."在fName中的位置。
            int dotIndex = fName.lastIndexOf(".");
            if (dotIndex < 0) {
                return type;
            }
            /* 获取文件的后缀名 */
            String end = fName.substring(dotIndex, fName.length()).toLowerCase();
            if (end == "")
                return type;
            // 在MIME和文件类型的匹配表中找到对应的MIME类型。
            for (int i = 0; i < MIME_MapTable.length; i++) {
                if (end.equals(MIME_MapTable[i][0]))
                    type = MIME_MapTable[i][1];
            }
            return type;
        }
    
        private final String[][] MIME_MapTable = { //名称后缀和MIME类型
                // {后缀名,MIME类型}
                {".3gp", "video/3gpp"},
                {".apk", "application/vnd.android.package-archive"},
                {".asf", "video/x-ms-asf"},
                {".avi", "video/x-msvideo"},
                {".bin", "application/octet-stream"},
                {".bmp", "image/bmp"},
                {".c", "text/plain"},
                {".class", "application/octet-stream"},
                {".conf", "text/plain"},
                {".cpp", "text/plain"},
                {".doc", "application/msword"},
                {".docx",
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
                {".xls", "application/vnd.ms-excel"},
                {".xlsx",
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
                {".exe", "application/octet-stream"},
                {".gif", "image/gif"},
                {".gtar", "application/x-gtar"},
                {".gz", "application/x-gzip"},
                {".h", "text/plain"},
                {".htm", "text/html"},
                {".html", "text/html"},
                {".jar", "application/java-archive"},
                {".java", "text/plain"},
                {".jpeg", "image/jpeg"},
                {".jpg", "image/jpeg"},
                {".js", "application/x-javascript"},
                {".log", "text/plain"},
                {".m3u", "audio/x-mpegurl"},
                {".m4a", "audio/mp4a-latm"},
                {".m4b", "audio/mp4a-latm"},
                {".m4p", "audio/mp4a-latm"},
                {".m4u", "video/vnd.mpegurl"},
                {".m4v", "video/x-m4v"},
                {".mov", "video/quicktime"},
                {".mp2", "audio/x-mpeg"},
                {".mp3", "audio/x-mpeg"},
                {".mp4", "video/mp4"},
                {".mpc", "application/vnd.mpohun.certificate"},
                {".mpe", "video/mpeg"},
                {".mpeg", "video/mpeg"},
                {".mpg", "video/mpeg"},
                {".mpg4", "video/mp4"},
                {".mpga", "audio/mpeg"},
                {".msg", "application/vnd.ms-outlook"},
                {".ogg", "audio/ogg"},
                {".pdf", "application/pdf"},
                {".png", "image/png"},
                {".pps", "application/vnd.ms-powerpoint"},
                {".ppt", "application/vnd.ms-powerpoint"},
                {".pptx",
                        "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
                {".prop", "text/plain"}, {".rc", "text/plain"},
                {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"},
                {".sh", "text/plain"}, {".tar", "application/x-tar"},
                {".tgz", "application/x-compressed"}, {".txt", "text/plain"},
                {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"},
                {".wmv", "audio/x-ms-wmv"},
                {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"},
                {".z", "application/x-compress"},
                {".zip", "application/x-zip-compressed"}, {"", "*/*"}};
       Uri data;
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            data = FileProvider7.getUriForFile(getContext(), file);
             // 给目标应用一个临时授权
             openintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
          } else {
               data = Uri.fromFile(file);
          }
             String type = getMIMEType(file);
          // 设置intent的data和Type属性。
          openintent.setDataAndType(/* uri */data, type);
                  
    
  • Catgory

    指定当前动作被执行的环境

    ① CATGORY_lAUNCHER 该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。

    ② CATGORY_BROWSABLE 设置组件可以使用浏览器启动,表示该activity只能用来浏览网页

    ③ CATGORY_DEFULT:android 默认执行方式,所有的Intent都可以激活它

  • Extra

    携带数据请求

     //跳转到网页
            Intent intent = new Intent();
            intent.setData(Uri.parse("http://www.baidu.com"));
            intent.setAction(Intent.ACTION_VIEW);
            intent.addCategory(Intent.CATEGORY_BROWSABLE);
            startActivity(intent);
    
     //跳转地图
            Intent mapIntent = new Intent();
            mapIntent.setData(Uri.parse("geo:38.899533,-77.036476")); 
            mapIntent.setAction(Intent.ACTION_VIEW);
            mapIntent.addCategory(Intent.CATEGORY_BROWSABLE);
            startActivity(mapIntent);
    
    //拨打电话-调用拨号盘
            Intent telIntent = new Intent();
            telIntent.setData(Uri.parse("tel:18210165501"));
            telIntent.setAction(Intent.ACTION_DIAL);
            startActivity(telIntent);
    
    //拨打电话-直接拨号
    //要使用这个必须在配置文件中加入
    //需要动态调用相关权限,不能仅仅在manifest中声明
            Intent telIIntent = new Intent();
            telIIntent.setData(Uri.parse("tel:18210165501"));
            telIIntent.setAction(Intent.ACTION_CALL);
            startActivity(telIIntent);
    
    //调用发送短信程序(方法一)
            Uri uri = Uri.parse("smsto:15980665805");
            Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
            intent.putExtra("sms_body", "The SMS text");
            startActivity(intent);
    //调用发送短信程序(方法二)
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.putExtra("sms_body", "The SMS text");
            intent.setType("vnd.android-dir/mms-sms");
            startActivity(intent);
    //发送彩信
            Uri uri = Uri.parse("content://media/external/images/media/23");
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.putExtra("sms_body", "some text");
            intent.putExtra(Intent.EXTRA_STREAM, uri);
            intent.setType("image/png");
            startActivity(intent);
    
    //发送Email(方法一)(要在 Android 手机上才能测试)
            Uri uri = Uri.parse("mailto:[email protected]");
            Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
            startActivity(intent);
    
    //发送Email(方法二)(要在 Android 手机上才能测试)
            Intent intent = new Intent(Intent.ACTION_SENDTO);
            intent.setData(Uri.parse("mailto:[email protected]"));
            intent.putExtra(Intent.EXTRA_SUBJECT, "这是标题");
            intent.putExtra(Intent.EXTRA_TEXT, "这是内容");
            startActivity(intent);
    
    //发送Email(方法三)(要在 Android 手机上才能测试)
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.putExtra(Intent.EXTRA_EMAIL, "[email protected]");
            intent.putExtra(Intent.EXTRA_SUBJECT, "这是标题");
            intent.putExtra(Intent.EXTRA_TEXT, "这是内容");
            intent.setType("text/plain");
            //选择一个邮件客户端
            startActivity(Intent.createChooser(intent, "Choose Email Client"));
    
    //        发送Email(方法四)(要在 Android 手机上才能测试)
            Intent intent = new Intent(Intent.ACTION_SEND);
            //收件人
            String[] tos = {"[email protected]", "[email protected]"};
            //抄送人
            String[] ccs = {"[email protected]", "[email protected]"};
            //密送人
            String[] bcc = {"[email protected]", "[email protected]"};
            intent.putExtra(Intent.EXTRA_EMAIL, tos);
            intent.putExtra(Intent.EXTRA_CC, ccs);
            intent.putExtra(Intent.EXTRA_BCC, bcc);
            intent.putExtra(Intent.EXTRA_SUBJECT, "这是标题");
            intent.putExtra(Intent.EXTRA_TEXT, "这是内容");
            intent.setType("message/rfc822");
            startActivity(Intent.createChooser(intent, "Choose Email Client"));
    
    //发送Email且发送附件(要在 Android 手机上才能测试)
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
            intent.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mp3/醉红颜.mp3");
            intent.setType("audio/mp3");
            startActivity(Intent.createChooser(intent, "Choose Email Client"));
    
    //播放媒体文件(android 对中文名的文件支持不好)
            Intent intent = new Intent(Intent.ACTION_VIEW);
            //Uri uri = Uri.parse("file:///sdcard/zhy.mp3");
            Uri uri = Uri.parse("file:///sdcard/a.mp3");
            intent.setDataAndType(uri, "audio/mp3");
            startActivity(intent);
                
            Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent)
                
            Intent intent2 = new Intent(Intent.ACTION_CHOOSER);
            intent2.putExtra(Intent.EXTRA_INTENT, intent1);
            intent2.putExtra(Intent.EXTRA_TITLE, "aaaa");
            startActivity(intent2);
    
    //设置壁纸
            Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
            startActivity(Intent.createChooser(intent, "设置壁纸"));
    
    //卸载APK
    //fromParts方法
    //参数1:URI 的 scheme
    //参数2:包路径
    //参数3:
            Uri uri = Uri.fromParts("package", "com.yobin.testintent", null);
            Intent intent = new Intent(Intent.ACTION_DELETE, uri);
            startActivity(intent);
    
    //安装APK(???)
            Uri uri = Uri.fromParts("package", "com.great.activity_intent", null);
            Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, uri);
            startActivity(intent);
    
    //调用搜索
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_WEB_SEARCH);
            intent.putExtra(SearchManager.QUERY, "android");
            startActivity(intent);
    
    
    
    
    
     
    

四、CreateChooser()的作用

  1. 如果有多个应用可以响应Intent,选择要使用的应用后,并设置默认选项后,那么每次都会执行该默认操作,但是如果用户希望每次使用不同应用,用createChooser()可以强制显示选择对话框,并且无法设置默认操作。

            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, "你好,是什么出现");
            sendIntent.setType("text/plain"); //发送短信
            Intent chooseIntent = Intent.createChooser(sendIntent, "这是选择的应用"); //包裹原始intent
            if (chooseIntent.resolveActivity(getPackageManager()) != null) {//判断该intent是否有activity意图
                startActivity(chooseIntent);
            }
    
  1. 如果没有应用响应,使用原始的startActivtiy,如果没有去resolveActivty方法判断,会抛出ActivityNotFoundException,而用createChooser会显示无应用可以执行操作

  2. 用于过滤不需要的应用显示在弹窗中

     public void clickView(View view) { 
            Intent sendIntent = getIntent(); 
         //遍历查询所有可以打开页面信息
            List resolveInfosNew = context.getPackageManager().queryIntentActivities(sendIntent, 0); 
            List targetIntents = new ArrayList<>();
            if (!resolveInfosNew.isEmpty()) { 
                for (ResolveInfo resolveInfo : resolveInfosNew) {
                    ActivityInfo activityInfo = resolveInfo.activityInfo;
                    String packageName = activityInfo.packageName; //可以利用packageName来进行过滤
                    if (!packageName.equals("com.android.bluetooth")) { //需要过滤的蓝牙
                        Intent intent = getIntent();
                        intent.setComponent(new ComponentName(packageName, activityInfo.name));//设置组件信息
                        targetIntents.add(intent);
                    }
                }
            }
    
            if (targetIntents.size() > 0) {
                Intent chooseIntent = Intent.createChooser(new Intent(), "这是选择的应用"); //包裹实际的应用
                //将需要的intent加入到chooseIntent中
                chooseIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
                if (chooseIntent.resolveActivity(getPackageManager()) != null) { //解析是否有intent对应的activity.
                    startActivity(chooseIntent);
                }
            }
        }
    
        public Intent getIntent() { //需要加载的意图
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_SEND);
            intent.putExtra(Intent.EXTRA_TEXT, "你好呢,哈哈");
            intent.setType("text/plain");
            return intent;
        }
    

五、接收隐式Intent

要公布应用可以接收哪些隐式Intent,需要在清单文件中使用intent-filter元素为每个应用组件声明一个或多个Intent过滤器,每个过滤器可以有,,三个组成

  1. 声明可以接收的操作,可以自定义,但是该值必须是操作的文本字符串,不可以是类常量

  2. 使用一个或多个指定数据URI(scheme、host、port、path),各个方面和MIME类型属性,声明接收的数据类型。

    注意:每个元素均可以指定URI结构和数据类型,URI包括scheme、host、port、path

    ://:/

    content://com.yobin.project:200/folder/subfolder/etc
    架构:content
    主机:com.yobin.project
    端口:200
    路径:folder/subfolder/etc
    上述属性存在依赖关系
        1. 如果没有指定架构,就忽略主机
        2. 没有指定主机,忽略端口
        3. 未指定主机和架构,忽略路径
        
    当Intent中URI与过滤器中URI规范进行比较时候,仅与过滤器包含的部分URI进行比较
        1. 如果过滤器仅指定架构,则具有该架构的所有URI均与过滤器匹配
        2. 如果过滤器指定架构和权限,但未指定路径,则具有相同架构和权限的所有 URI 都会通过过滤器,无论其路径如何均是如此
        3. 如果过滤器指定架构、权限和路径,则仅具有相同架构、权限和路径的 URI 才会通过过滤器
        注意: 路径规范可以包含星号通配符 (*),因此仅需部分匹配路径名即可
    数据测试会将 Intent 中的 URI 和 MIME 类型与过滤器中指定的 URI 和 MIME 类型进行比较。规则如下:
        1. 仅当过滤器未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。
        2. 对于包含 URI 但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与过滤器的 URI 格式匹配、且过滤器同样未指        定 MIME 类型时,才会通过测试。
        3.仅当过滤器列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型但不含 URI 的 Intent 才会通过测试。
        4.仅当 MIME 类型与过滤器中列出的类型匹配时,同时包含 URI 类型和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的       MIME 类型部分。如果 Intent 的 URI 与过滤器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: URI 且过滤器未指定 URI,则             Intent 会通过测试的 URI 部分。换言之,如果过滤器只是列出 MIME 类型,则假定组件支持 content: 和 file: 数据
    注意:指定了Intent的URI和MIME类型,如果数据中没有,则匹配失败。      
        
    
  1. name属性中声明接收类别,必须是可以操作的文本字符串值,不能为常量。注意,接收隐式Intent必须将CATEGORY_DEFAULT类别包括在Intent过滤器中,startActivity()和startActivityForResult()将按照其声明类别处理所有Intent,如果没有此声明,那么隐式Intent不会解析Activity.
    
    
    
        
        
    
   

    
    
    
        
        
        
    
    
    
        
        
        
        
        
        
    

注意

本文是来源是Android开发者网站,以及部分网址,进行了相关的整理,增加了部分自己的东西。

Android developer

Intent属性详解二 Action、Category

intent隐式调用大全(调用系统的的组件)

createchooser应用选择器

你可能感兴趣的:(Intent相关)