【Android必备】构建一个App Widget主机(25)

概要


大多数Android设备上提供的Android主屏幕允许用户嵌入应用窗口小部件以快速访问内容。如果您正在构建Home替代品或类似的应用程序,则还可以通过实施一个允许用户嵌入应用程序小部件 AppWidgetHost。这不是大多数应用程序需要做的事情,但是如果您要创建自己的主机,了解主机默认同意的合同义务很重要。

本文件重点介绍实施习俗所涉及的责任 AppWidgetHost。有关如何实现an的示例 AppWidgetHost,请参阅Android主屏幕 Launcher的源代码 。

以下是实现定制所涉及的关键类和概念的概述 AppWidgetHost:

  • App Widget Host - AppWidgetHost为应用程序提供与AppWidget服务的交互,例如主屏幕,这些应用程序想要在其UI中嵌入应用程序窗口小部件。一个AppWidgetHost必须有一个ID,它是主机本身的包中是唯一的。该ID在主机的所有用途中保持不变。该ID通常是您在应用程序中分配的硬编码值。
  • App Widget ID - 每个应用程序小部件实例在绑定时都被分配一个唯一的ID(请参阅绑定应用程序小部件bindAppWidgetIdIfAllowed()中更详细的讨论)。唯一ID由主机使用获得。这个ID在小部件的整个生命周期中都是持久的,也就是说,直到它从主机中删除。任何主机特定的状态(如小部件的大小和位置)都应由主机包持久保存并与应用部件ID相关联。 allocateAppWidgetId()
  • 应用小部件主机视图 - AppWidgetHostView可以被视为小部件需要显示时包裹的框架。AppWidgetHostView每次小部件被主机充气时,都会将应用程序小部件分配给该部件。
  • 选项包 - AppWidgetHost使用选项包将信息传递给AppWidgetProvider有关如何显示小部件的信息(例如,大小范围以及小部件是在锁定屏幕还是主屏幕上)。该信息允许 AppWidgetProvider根据显示的方式和位置来定制窗口小部件的内容和外观。您使用 updateAppWidgetOptions() 和 updateAppWidgetSize() 修改应用程序窗口小部件的包。这两种方法都会触发回调函数 AppWidgetProvider。

绑定应用小部件


当用户将应用程序小部件添加到主机时,会发生称为绑定的过程 。绑定是指将特定的应用部件ID关联到特定的主机和特定的 AppWidgetProvider。有不同的方式来实现这一点,这取决于您的应用在哪个版本的Android上运行。

在Android 4.0及更低版本上绑定应用程序小部件
在运行Android 4.0及更低版本的设备上,用户通过允许用户选择小部件的系统活动添加应用小部件。这隐式做了权限检查 - 即通过添加应用小部件,用户隐式授予您的应用向应用主机添加应用小部件的权限。下面是一个例子,说明了这种方法,取自原始的 Launcher。在这段代码中,事件处理程序响应用户操作调用 startActivityForResult() 请求代码REQUEST_PICK_APPWIDGET:

private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPWIDGET = 9;
...
public void onClick(DialogInterface dialog, int which) {
    switch (which) {
    ...
        case AddAdapter.ITEM_APPWIDGET: {
            ...
            int appWidgetId =
                    Launcher.this.mAppWidgetHost.allocateAppWidgetId();
            Intent pickIntent =
                    new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
            pickIntent.putExtra
                    (AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            ...
            startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
            break;
    }
    ...
}

当系统活动结束时,它会将用户选择的应用程序小部件的结果返回到您的活动。在以下示例中,该活动通过调用addAppWidget()以添加应用程序小部件来进行响应:

public final class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener {
    ...
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        mWaitingForResult = false;

        if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
            switch (requestCode) {
                ...
                case REQUEST_PICK_APPWIDGET:
                    addAppWidget(data);
                    break;
                case REQUEST_CREATE_APPWIDGET:
                    completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked);
                    break;
                }
        }
        ...
    }
}

该方法addAppWidget()检查应用程序窗口小部件是否需要在添加之前进行配置:

void addAppWidget(Intent data) {
    int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

    String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);
    AppWidgetProviderInfo appWidget =
            mAppWidgetManager.getAppWidgetInfo(appWidgetId);

    if (appWidget.configure != null) {
        // Launch over to configure widget, if needed.
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
        intent.setComponent(appWidget.configure);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
    } else {
        // Otherwise, finish adding the widget.
    }
}

有关配置的更多讨论,请参阅创建App Widget配置活动。

一旦应用程序小部件准备就绪后,下一步就是将其添加到工作区的实际工作。在 原发射使用称为方法completeAddAppWidget() 来做到这一点。

在Android 4.1和更高版本上绑定应用程序窗口小部件

Android 4.1增加了更简化的绑定过程的API。这些API还可以让主机为绑定提供自定义用户界面。要使用这个改进的过程,您的应用程序必须BIND_APPWIDGET在其清单中声明 权限:

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

但这只是第一步。在运行时,用户必须明确授予您的应用程序权限,以允许它向主机添加应用程序窗口小部件。要测试您的应用是否具有添加小部件的权限,请使用该 bindAppWidgetIdIfAllowed() 方法。如果bindAppWidgetIdIfAllowed() 返回false,您的应用程序必须显示一个对话框,提示用户授予权限(“允许”或“始终允许”,以涵盖所有未来的应用程序小部件添加)。这段代码给出了一个如何显示对话框的例子:

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle discussed above
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);

主机还必须检查用户是否添加了需要配置的应用程序窗口小部件。有关此主题的更多讨论,请参阅 创建应用程序小部件配置活动

主持人的责任


小部件开发人员可以使用 AppWidgetProviderInfo元数据为小部件指定一些配置设置。这些配置选项将在下面更详细讨论,主机可以从AppWidgetProviderInfo 与窗口小部件提供程序关联的对象中检索这些配置选项。

无论您的Android版本为何,所有主机都有以下责任:

  • 添加小部件时,您必须按上述方式分配小部件ID。您还必须确保从主机中移除小部件时,您会调用deleteAppWidgetId() 解除分配小部件ID。
  • 添加小部件时,请确保在配置活动存在的情况下启动其配置活动,如配置活动中的 更新App Widget中所述。这是许多应用程序小部件在正确显示之前的必要步骤。
  • 每个应用程序小部件都指定了dps中的最小宽度和高度,如AppWidgetProviderInfo元数据中所定义(使用android:minWidth和 android:minHeight)。确保这个小部件的布局至少有这么多dps。例如,许多主机将网格中的图标和小部件对齐。在这种情况下,默认情况下,主机应使用满足细胞的最小数量添加的应用小工具minWidth和minHeight约束。

除了上面列出的要求外,特定的平台版本还引入了在主机上增加新职责的功能。

您定位的是哪个版本?
您在实现主机时使用的方法应取决于您的目标Android版本。本节中介绍的许多功能都是在3.0或更高版本中引入的。例如:

  • Android 3.0(API Level 11)为小部件引入了自动预先行为。
  • Android 3.1(API Level 12)引入了调整窗口小部件的功能。
  • Android 4.0(API Level 15)引入了填充策略的变化,该策略将责任置于主机上以管理填充。
  • Android 4.1(API Level 16)添加了一个API,允许小组件提供者获取有关其小组件实例所处环境的更多详细信息。
  • Android 4.2(API Level 17)引入了选项包和 bindAppWidgetIdIfAllowed() 方法。它还引入了锁屏小部件。

如果您定位的是早期的设备,请参阅原始的 Launcher作为示例。

以下各节提供了有关在主机上增加新责任的功能的更多详细信息。

Android 3.0
Android 3.0(API Level 11)引入了小部件指定的功能autoAdvanceViewId()。这个视图ID应该指向某个实例 Advanceable,比如StackView 或AdapterViewFlipper。这表明主持人应该在主持人advance()认为适当的时间间隔内调用此视图(考虑是否有必要推进小部件 - 例如,如果主持人在另一个小部件上,主持人可能不希望推进小部件页面,或者如果屏幕关闭)。

Android 3.1
Android 3.1(API Level 12)引入了调整窗口小部件的功能。小部件可以使用 元数据中的android:resizeMode 属性指定其大小 AppWidgetProviderInfo,并指示它是否支持水平和/或垂直大小调整。在Android 4.0(API Level 14)中引入,该小部件还可以指定一个 android:minResizeWidth 和/或android:minResizeHeight。

主持人有责任让小部件按照小部件的指定水平和/或垂直调整大小。指定可调整大小的小部件可以任意调整大小,但不应调整为小于android:minResizeWidth and 指定的值android:minResizeHeight。有关示例实现,请 在。 AppWidgetResizeFrameLauncher2

Android 4.0
Android 4.0(API Level 15)引入了填充策略的变化,该策略将责任置于主机上以管理填充。从4.0开始,应用部件不再包含自己的填充。相反,系统会根据当前屏幕的特征为每个小部件添加填充。这导致网格中的小部件更统一,一致的呈现。为了协助托管应用程序小部件的应用程序,该平台提供了该方法 getDefaultPaddingForWidget()。应用程序可以调用此方法来获取系统定义的填充并在计算要分配给窗口小部件的单元数时进行计算。

Android 4.1
Android 4.1(API Level 16)添加了一个API,允许小组件提供者获取有关其小组件实例所处环境的更多详细信息。具体来说,主机向窗口小部件提供者提示窗口小部件的显示大小。提供这种尺寸信息是主人的责任。

主机通过提供此信息 updateAppWidgetSize()。大小以dps指定为最小和最大宽度/高度。指定范围的原因(与固定大小相反)是因为小部件的宽度和高度可能随着方向而改变。您不希望主机不得不更新其所有小部件,因为这可能会导致严重的系统减速。这些值应该在放置窗口小部件时更新一次,任何时候窗口小部件被调整大小,以及任何时候启动程序在给定的启动时第一次膨胀窗口小部件(因为这些值不会在启动时持续存在)。

Android 4.2
Android 4.2(API Level 17)增加了在绑定时指定选项包的功能。这是指定应用程序窗口小部件选项(包括大小)的理想方式,因为它AppWidgetProvider可以在第一次更新时立即访问选项数据。这可以通过使用该方法来实现bindAppWidgetIdIfAllowed()。有关此主题的更多讨论,请参阅绑定应用程序小部件。

Android 4.2还引入了锁屏小部件。当在锁定屏幕上托管窗口小部件时,主机必须在应用窗口小部件选项集中指定此信息(AppWidgetProvider可以使用此信息来适当地设置窗口小部件的样式)。要指定一个窗口小部件作为锁屏窗口小部件,请使用updateAppWidgetOptions() 该字段OPTION_APPWIDGET_HOST_CATEGORY 并在其中包含 该值WIDGET_CATEGORY_KEYGUARD。此选项默认为WIDGET_CATEGORY_HOME_SCREEN,所以不需要明确要求为主屏幕主机设置此选项 。

确保您的主机只添加适合您的应用的应用小部件 - 例如,如果您的主机是主屏幕,请确保元数据中的 android:widgetCategory 属性 AppWidgetProviderInfo包含该标志WIDGET_CATEGORY_HOME_SCREEN。同样,对于锁定屏幕,请确保该字段包含该标志 WIDGET_CATEGORY_KEYGUARD。有关此主题的更多讨论,请参阅 在锁定屏幕上启用应用程序窗口小部件。

Lastest Update:2018.04.27

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Android必备】构建一个App Widget主机(25)

猜你喜欢

转载自blog.51cto.com/4789781/2122508