美文网首页
Intent相关

Intent相关

作者: Yobin_He | 来源:发表于2020-06-08 14:33 被阅读0次

    一、定义

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

    • 启动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);
      
      //拨打电话-直接拨号
      //要使用这个必须在配置文件中加入<uses-permission android:name="android.permission.CALL_PHONE"/>
      //需要动态调用相关权限,不能仅仅在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:zhangsan@gmail.com");
              Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
              startActivity(intent);
      
      //发送Email(方法二)(要在 Android 手机上才能测试)
              Intent intent = new Intent(Intent.ACTION_SENDTO);
              intent.setData(Uri.parse("mailto:zhangsan@gmail.com"));
              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, "me@abc.com");
              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 = {"to1@abc.com", "to2@abc.com"};
              //抄送人
              String[] ccs = {"cc1@abc.com", "cc2@abc.com"};
              //密送人
              String[] bcc = {"bcc1@abc.com", "bcc2@abc.com"};
              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<ResolveInfo> resolveInfosNew = context.getPackageManager().queryIntentActivities(sendIntent, 0); 
              List<Intent> 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过滤器,每个过滤器可以有<action>,<data>,<category>三个组成

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

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

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

      <scheme>://<host>:<port>/<path>

      content://com.yobin.project:200/folder/subfolder/etc
      架构<scheme>:content
      主机<host>:com.yobin.project
      端口<port>:200
      路径<path>: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类型,如果数据中没有<data>,则匹配失败。      
          
      
    1. <category> name属性中声明接收类别,必须是可以操作的文本字符串值,不能为常量。注意,接收隐式Intent必须将CATEGORY_DEFAULT类别包括在Intent过滤器中,startActivity()和startActivityForResult()将按照其声明类别处理所有Intent,如果没有此声明,那么隐式Intent不会解析Activity.
        <activity android:name="MainActivity">
        <!-- This activity is the main entry, should appear in app launcher -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
       </activity>
    
        <activity android:name="ShareActivity">
        <!-- This activity handles "SEND" actions with text data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
        <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <action android:name="android.intent.action.SEND_MULTIPLE"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="application/vnd.google.panorama360+jpg"/>
            <data android:mimeType="image/*"/>
            <data android:mimeType="video/*"/>
        </intent-filter>
    </activity>
    

    注意

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

    Android developer

    Intent属性详解二 Action、Category

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

    createchooser应用选择器

    相关文章

      网友评论

          本文标题:Intent相关

          本文链接:https://www.haomeiwen.com/subject/txbgzhtx.html