Android OtherAndroid开发Android知识

Android知识点回顾之Intent/IntentFilter

2017-10-30  本文已影响32人  星泉毅

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

可以用于以下三个场景:

startActivity()
 startActivityForResult()
  startService();
  bindService();
sendBroadCast()
sendOrderedBroadCast()
sendStickyBroadcast()

Intent 类型

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

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

Intent的创建

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

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

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

显示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进行使用
主要有如下的使用场景:

取得实例的方法如下:
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 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 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>://<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);
}

本知识点完~

上一篇 下一篇

猜你喜欢

热点阅读