Android知识点回顾之Intent/IntentFilter

定义: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中的<data>结构由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

整体组成:<scheme>://<host>:<port>/<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);
}

本知识点完~

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

推荐阅读更多精彩内容