Android知识点回顾之Intent/IntentFilter

Android知识点回顾之Intent/IntentFilter此项是可选的,用来区分显示Intent和隐式Intent。 不定期补充… 根据给定的Uri寻找匹配的目标组件,如果不给定MIME类型,会进行推导,给定MIME类型,则强制使用此类型。 不同的Action有对应的data数据指定。 tel://: 号码数据格式,后跟电话号码。…

定义:Intent是一个消息传送对象,可以用它来访问另外一个组件

可以用于以下三个场景:

  • startActivity
startActivity()
 startActivityForResult()
  • startService
    Android 5.0以上可以使用JobScheduler启动
    所有版本可以使用:
    startService();
    bindService();
  • sendBroadcast
    三种调用方法
    sendBroadCast()
    sendOrderedBroadCast()
    sendStickyBroadcast()

Intent 类型

  • 显示类型
    直接指定调用组件的名字,一般用于自己的APP内部
  • 隐式类型
    没有指定组件的名字,而是声明一般的action行为,用此方法可以允许调用另外一个APP的组件

启动Service最好使用显示Intent,否则会存在安全风险,因为无法确定service什么时候被调用,而service又是用户感知不到的组件

Android 5.0开始,如果bindService()隐式调用启动service,会抛出异常

Intent的创建

一个Intent对象包含了Android系统应该启动哪个组件的信息

一个Intent可以包含以下信息:

  • componentName
    指定需要启动组件的名字
    此项是可选的,用来区分显示Intent和隐式Intent。
    赋值的方法有以下几种

    • Intent的构造方法
    • setComponent()
    • setClass()
    • setClassName
  • action
    指定Intent要完成的动作,为字符串常量
    action可自定义,也可使用系统的,一般自定义的话最好加上自己APP的包名前缀
    一些系统标准的Action常量
    ACTION_VIEW,startActivity(),唤起系统相册
    ACTION_SEND,startActivity(),把一些数据发送给另外的一些APP,如email,社交软件等
    ACTION_CALL,startActivity(),唤起打电话界面
    不定期补充…
    除了Intent定义了Action常量,其他的类也有定义,比如Settings,可以用来跳转到系统指定的设置界面
    action赋值的方法有一下几种:

    • Intent的构造方法
    • setAction()
  • data
    根据给定的Uri寻找匹配的目标组件,如果不给定MIME类型,会进行推导,给定MIME类型,则强制使用此类型。
    不同的Action有对应的data数据指定。
    其中data的值设置为setData(),MIME的设置为setType()
    常用值如下所示:
    tel://:      号码数据格式,后跟电话号码。 
    mailto://:    邮件数据格式,后跟邮件收件人地址。
    smsto://:    短息数据格式,后跟短信接收号码。
    content://:   内容数据格式,后跟需要读取的内容。 
    file://:      文件数据格式,后跟文件路径。
    geo:// latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
    Uri指定数据指向那种数据格式,MIME指定数据具体的类型。比如Image和Audio有同样的Uri,但是MIME的类型是不同的。

    setData()和setType()会互相覆盖,所以当需要同时设置Uri和MIME时,为了避免这种情况,可以调用setDataAndType()

  • category
    执行Action的附加信息。可以放置很多category,但是大多数intent是不需要category的
    常用值如下:
    CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。 
    CATEGORY_HOME:设置该组件为Home Activity。
    CATEGORY_PREFERENCE:设置该组件为Preference。 
    CATEGORY_LAUNCHER:设置该组件为在当前应用程序启动器中优先级最高的Activity,通常为入口ACTION_MAIN配合使用。 
    CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。 
    CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
    通过addCategory()指定
  • extras
    用来存放需要传递的数据,以键值对的形式进行存储和访问
    通过putExtras()方法设置
  • flags
    设置Activity的启动模式,例如:
    FLAG_ACTIVITY_CLEAR_TOP
    FLAG_ACTIVITY_NEW_TASK
    FLAG_ACTIVITY_NO_HISTORY
    FLAG_ACTIVITY_SINGLE_TOP
    具体的笔记放到Activity上
    通过setFlags()方法设置

显示Intent的例子

Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

隐式Intent的例子

其中resolveActivity()用来判断Intent是否能够被解析,防止APP崩溃

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
//Intent chooser = Intent.createChooser(sendIntent, title);//强制使用选择器
//if (sendIntent.resolveActivity(getPackageManager()) != null) {
// startActivity(chooser);
//}
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

接收一个隐式Intent

需要在manifest文件中配置<intent-filter>,<intent-filter>包含如下三个子项:
<action>
<data>
<category>

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

MIME类型 application/vnd.google.panorama360+jpg为指定的全景照片数据类型

<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>

使用PendingIntent

PendingIntent是对Intent的包装,使外部的APP能够像在内部APP那样对所包含的Intent进行使用
主要有如下的使用场景:

  • Notification
  • App Widget
  • AlarmManager

取得实例的方法如下:
PendingIntent.getActivity(),启动Activity
PendingIntent.getService(),启动Service
PendingIntent.getBroadcast(),启动BroadcastReceiver

状态栏通知:

  int icon = android.R.drawable.my_icon;
  long when = System.currentTimeMillis();//通知发生的时间为系统当前时间
  Notification notification = new Notification(icon, null, when);//新建一个通知,第一个参数为图标,第二个参数为短暂提示标题,第三个为通知时间
  notification.defaults = Notification.DEFAULT_SOUND;//发出默认声音
  notification.flags |= Notification.FLAG_AUTO_CANCEL;//点击通知后自动清除通知
  Intent openintent = new Intent(this, OtherActivity.class);
  PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图
  notification.setLatestEventInfo(this, "标题", "内容", contentIntent);//setLatestEventInfo表示设置点击该通知的事件
    int notifyCode = 0;
//获取通知管理器
  NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  mNotificationManager.notify(notifyCode , notification);//第一个参数为自定义的通知唯一标识

action匹配规则

如果intent-filter设置了action的过滤规则,比如下面的XML代码,

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

那么:

  • intent不设置action,则直接不通过
  • intent设置了多个Action,则只要有一个匹配上,则可以通过
    //不通过
    Intent intent = new Intent();
    //通过
    intent.setAction("android.intent.action.EDIT");
    //通过
    intent.setAction("android.intent.action.EDIT");
    intent.setAction("android.intent.action.test");

    Category匹配规则

    如果intent-filter设置了category的过滤规则,如下面的XML代码,

    <intent-filter>
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      ...
    </intent-filter>

    那么:

  • Intent不设置category,则都通过,不论intent-filter设置多少category
  • intent设置了category,intent上的category能够匹配上intent-filter设置的category,才能够通过

比如:

//通过
Intent intent = new Intent();
//通过
intent.addCategory("android.intent.category.DEFAULT"),可以匹配上
//通过
intent.addCategory("android.intent.category.BROWSABLE")
//不通过
intent.addCategory("android.intent.category.DEFAULT")
intent.addCategory("android.intent.category.test")

Data匹配规则

intent-filter中的结构由Uri和MIME Type组成
Uri包括如下几部分:

  • scheme:整个Uri的模式,如http,ftp,content等
    如果scheme未指定,则忽略host
    如果只指定scheme,则所有和intent-filter相同的scheme都匹配

  • host:Uri的域名,如www.google.com
    如果host未指定,则忽略port

  • port:Uri的端口

  • path:包含的路径信息,如:folder/subfolder/etc
    如果scheme,host都未指定,则忽略path

整体组成:://:/,如 content://com.example.project:200/folder/subfolder/etc

MIME Type:表示image/ipeg,video/*等媒体类型

匹配规则如下:
intent中的data必须和intent-filter完全匹配才能通过。有如下几种情况:
a.intent没有设置Uri和MIME Type,同时intent-filter也没有设置
b.intent只包含Uri,但未包含MIME Type,同时能够匹配上intent-filter设置的Uri,并且intent-filter为设置MIME Type
c.intent只设置MIME Type,同时intent-filter也设置了相同的MIME Type并且未指定Uri
d.intent设置了Uri和MIME Type,intent-filter只设置了MIME Type,则intent的Uri的scheme必须为content:或是file:。即,intent-filter如果没有设置Uri,只设置了MIME Type,则Uri为content:或file:的模式。也就是说,过滤的规则希望组件能够从文件(file)或内容提供者(content provider)获取到本地数据。

规则d例子,从相册获取图片:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

则intent的匹配规则为:

 Intent intent = new Intent();
 intent.setDataAndType(Uri.parse("file://test"), "image/*");
 startActivity(intent);

如果intent-filter设置了多个data,则intent中的data只要和其中一个匹配就可以通过

为了防止APP崩溃,所有的intent匹配规则进行调用前都要进行判断处理:
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}

本知识点完~

今天的文章Android知识点回顾之Intent/IntentFilter分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14871.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注