您的位置:首页 > 移动开发 > Android开发

给隐式Intent加载运行检查(Android Development Patterns S1 Ep 1)

2016-09-26 01:14 435 查看

前言

2015年9月开始,谷歌在YouTube上上传了一系列开发指导视频,这是Android Development Patterns系列视频的第一期,标题为“Protecting Implicit Intents with Runtime Checks”

Intent 类型

Intent 类型

Intent 分为两种类型:

显式 Intent :按名称(完全限定类名)指定要启动的组件。通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。

隐式 Intent :不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

创建显式 Intent 启动 Activity 或服务时,系统将立即启动 Intent 对象中指定的应用组件。

创建隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 Intent 过滤器进行比较,从而找到要启动的相应组件。Intent如果 Intent 与 Intent 过滤器匹配,则系统将启动该组件,并将其传递给对象。如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。

Intent 过滤器是应用清单文件中的一个表达式,它指定该组件要接收的 Intent 类型。例如,通过为 Activity 声明 Intent 过滤器,您可以使其他应用能够直接使用某一特定类型的 Intent 启动 Activity。同样,如果您没有为 Activity 声明任何 Intent 过滤器,则 Activity 只能通过显式 Intent 启动。

警告:为了确保应用的安全性,启动 Service 时,请始终使用显式 Intent,且不要为服务声明 Intent 过滤器。使用隐式 Intent 启动服务存在安全隐患,因为您无法确定哪些服务将响应 Intent,且用户无法看到哪些服务已启动。从 Android 5.0(API 级别 21)开始,如果使用隐式 Intent 调用 bindService(),系统会抛出异常。



[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()。

[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。

[3] 找到匹配项之后,该系统通过调用匹配 Activity(Activity B)的 onCreate() 方法并将其传递给 Intent,以此启动匹配 Activity。

隐式 Intent 示例



应用1:My Application

应用2:Implicit Intent



在应用1中点击
Implicit Intent
按钮,发起隐式Intent,跳转到应用2。

构建隐式 Intent

如需声明对于应用接收的 Intent ,请确保将应用的软件包名称作为前缀。

My Application中,Button代码如下:

static final String IMPLICIT_INTENT = "com.example.journey.IMPLICIT_INTENT";

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sendIntent = new Intent();
sendIntent.setAction(IMPLICIT_INTENT);
startActivity(sendIntent);

}
});


接收隐式 Intent

要公布应用可以接收哪些隐式 Intent,请在清单文件中使用 <intent-filter> 元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。

注意:显式 Intent 始终会传递给其目标,无论组件声明的 Intent 过滤器如何均是如此。

应用组件应当为自身可执行的每个独特作业声明单独的过滤器。例如,图像库应用中的一个 Activity 可能会有两个过滤器,分别用于查看图像和编辑图像。 当 Activity 启动时,它将检查 Intent 并根据 Intent 中的信息决定具体的行为(例如,是否显示编辑器控件)。

Implicit Intent中,
Manifest.xml
文件声明如下

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.journey.implicitintent">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ScrollingActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="com.example.journey.IMPLICIT_INTENT"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

</activity>
</application>

</manifest>


运行结果



Build Better Apps

崩溃

如果这时候我卸载了Implicit Intent这个应用,那么此时点击button按钮,应用将会崩溃。



除了应用被卸载的情况外,还有以下情况会导致崩溃:

应用被禁用

用户的特定权限文件夹,不具有访问所有功能的属性

管理员限制了用户关于某些应用和属性的使用权限

解决办法

使用
resolveActivity


Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sendIntent = new Intent();
sendIntent.setAction(IMPLICIT_INTENT);

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android
相关文章推荐