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

前言

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(),系统会抛出异常。

 隐式 Intent 如何通过系统传递以启动其他 Activity
[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);
                }
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值