负责⼈:ˋ◇Aduil ﹎原文地址:developer.android/guide/topics/appwidgets/index.html
App Widgets 是⼀个应用程序的⼩视图,可以嵌⼊到其他应用程序(如主屏幕)并且能够定期更新。你可以发布⼀个应用程序的App Widget ,而这些视图称为窗⼝的用户界面。⼀个应用程序里,可以支持其他应用程序的App Widgets 称为App Widget 的主机。下面的截图是显示音乐的App Widget 。
该文档将介绍如何在应用程序里发布使用App Widget 。
基础知识-The Basics
要创建⼀个App Widget ,您需要了解以下⼏点:
AppWidgetProviderInfo 对象:
描述了⼀个App Widget 的元数据,如在App Widget 的布局,更新频率,和AppWidgetProvider 类。都应在XML 中定义。
AppWidgetProvider 类的实现:
定义⼀个基于广播事件与App Widget 的接⼝方法。通过它,您将收到广播对App Widget 进行更新,启用,禁用和删除。
视图布局:
在XML 中初步定义App Widget 布局。
此外,还可以实现App Widget 可配置的* Activity * 。当用户添加您的App Widget ,并允许他或她在创建时修改设置时启动这个可配置的Activity 。
以下各节描述如何设置这些组件。
Declaring an App Widget in the Manifest
首先,在您的应用程序的l 文件中声明* AppWidgetProvider * 类。例如:
1234567<receiver android:name ="ExampleAppWidgetProvider" >
<intent -filter >
<action android:name ="android.appwidget.action.APPWIDGET_UPDATE" /> </intent -filter >
<meta -data android:name ="android.appwidget.provider"
android:resource ="@xml/example_appwidget_info" />
</receiver >
android :name 属性,在App Widget 中指定使用AppWidgetProvider 。
<action>元素的android :name 属性。此属性指定AppWidgetProvider 接
受'''ACTION_APPWIDGET_UPDATE 广播。这是唯⼀的广播,你必须明确声明。在AppWidgetManager 自动发送其他App widget 广播AppWidgetProvider 是必要的。
<meta-data>元素指定的AppWidgetProviderInfo 的资源,需要以下属性:
android.appwidget.provider 识别作为AppWidgetProviderInfo 描述符的数据。
android:resource - 指定AppWidgetProviderInfo 的资源位置。
Adding the AppWidgetProviderInfo Metadata
AppWidgetProviderInfo 定义App Widget 的基本素质,例如其最⼩的布局尺⼨,其初始布局资源,如何经常更新App Widget ,和(可选)配置Activity ,在创建时发起。在XML 资源文件中定义AppWidgetProviderInfo 对象,使用<appwidget-provider>元素和在项目的RES / XML/文件夹中保存。
例如:
123456789<appwidget -provider xmlns:android ="schemas.android/apk/res/android" android:minWidth ="294dp"
android:minHeight ="72dp"
android:updatePeriodMillis ="86400000"
android:previewImage ="@drawable/preview"
android:initialLayout ="@layout/example_appwidget"
android:configure ="ample.android.ExampleAppWidgetConfigure" android:resizeMode ="horizontal|vertical">
</appwidget -provider >
以下是<appwidget-provider>属性的摘要:
App Widget默认的情况下MinHeight属性值指定消耗最⼩的空间,AppWidgets默认主页的屏幕位置,在其窗⼝基础上的单元格有⼀个明确高度和宽度的网格。如果⼀个App Widget的最⼩宽度或高度值不匹配单元格的尺⼨,则App Widget尺⼨四舍五⼊到最接近的单元格⼤⼩。
在App Widget Design Guidelines里了解更多关于App Widget的窗⼝⼤⼩。
注:为了使App Widget更容易在跨设备中携带,App Widget的最⼩尺⼨不应⼤于4×4单元格
minResizeHeight属性指定App Widget的绝对最⼩尺⼨。这些值应该指定尺⼨下,否则应用程序组件将无法辨认或以其他方式使用。在android3.1,允许用户使用这些属性调整控件⼤⼩,可能是⼩于默认尺⼨界定
的MinHeight属性。
在App Widget Design Guidelines里了解更多关于App Widget的窗⼝⼤⼩。
updateperiodmillis属性定义,往往在App Widget框架,应从Appwidgetprovider请求通过调用onUpdate()回调方法更新。实际上不能保证更新的准确性,我们建议尽可能的少更新或者不超过每⼩
时⼀次,以此来节省电池。你也可以在configuration-some中允许用户调整频率,比如证劵报价机,⼀些用户可能想要15分钟更新⼀次,⼀些则想要每天只更新四次
注:如果该设备是睡着的,而它是⼀个更新的时间(定义updatePeriodMillis)时,则该设备将被唤醒以执行更新。如果你不超过每⼩时更新⼀次,这可能不会对电池寿命造成重⼤的问题。但是,如果您需要频繁更新或你并不需要更新,而设备是睡着的,你就可以根据报警代替执行,则不会唤醒设备执行更新。要做到这⼀点,设置⼀个Intent,当您的AppWidgetProvider收到的报警时,使用AlarmManager。设置报警类型
有ELAPSED_REALTIME或RTC,这在收到报警时,该设备被唤醒。然后设置updatePeriodMillis为零("0")。initialLayout的属性指向布局资源,它定义了App Widget的布局。
在* Activity* 启动时对configure属性进行配置定义,用户添加App Widget,以便他或她配置App Widget属性。这是可选的(阅读下面创建⼀个App Widget配置的Activity)。
在配置android:previewImage进行在l文件中。在android3.0有相关介绍中。更多的讨论使用previewImage,请参阅设置预览图标。
在Android 3.0的介绍,该autoAdvanceViewId属性指定的App Widget⼦视图的视图ID,应该是auto-advanced 部件的主机。
在Android 3.1的介绍,该resizeMode,水平,垂直,或两轴。用户touch-hold⼀个⼩⼯具,以显示其调整手柄,然后拖动水平和/或垂直手柄,改变布局网格的⼤⼩。resizemode属性值包括"horizontal", "vertical", 和"none"。声明⼀个部件作为resizeable横向、纵向、以及“横向|垂直”的值。
参考AppWidgetProviderInfo类查看更多信息,关于被AppWidgetProviderInfo类的<appwidget-provider>元素接收的标示。
Creating the App Widget Layout
必须为你的App widget定义初始布局的XML和将其保存在项目的res/layout/目录中。使用下列的视图对象可以设计你的App widget,但在你开始设计你的App widget之前,请阅读和理解App widget的设计准则。
如果你熟悉XML的布局,创建App widget的布局很简单。然而,你们必须知道App widget的布局都是基于RemoteViews,不支持各种布局或视图控件。
⼀个RemoteViews对象(and, consequently, an App Widget)可以支持以下布局类:
FrameLayout
LinearLayout
RelativeLayout
及以下的⼩部件类:
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
这些类的⼦类都不支持的。
Adding margins to App Widgets
widget通常不应该扩展到屏幕边缘,不应与其他widget视图共同刷新,所以你应该增加边缘围绕你的widget框架。作为Android 4.0,App widget提供了⼩部件之间的自动填充框架和App widget的包围盒,以便用户在主屏幕更好的调整其他⼩部件和图标。使用这种推荐应用程序的targetSdkVersion设置14或更高。
它很容易编写⼀个布局,适用于早期版本的平台,具有自定义边距,在Android4.0并没有额外的边距或者更高:1.设置应用程序的targetsdkversion值为14或更高。 2.创建⼀个如下布局,引用其他尺⼨资源:
1 2 3 4 5 6 7 8 9 10 11 12<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/widget_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@drawable/my_widget_background"> …
</LinearLayout>
</FrameLayout>
3.创建两个维度的资源,⼀个在res/values-v14/没有为Android
4.0⼩部件提供额外的填充:
res/l:
1<dimen name="widget_margin">8dp</dimen>
res/l:
1<dimen name="widget_margin">0dp</dimen>
另⼀个选择是在默认情况下简单地构建额外的边距在你的nine-patch背景的assets,而没有边距在API级别14或之后并提供不同的nine-patches。
Using the AppWidgetProvider Class
你必须在AndroidManifest<receiver>元素里声明广播接收器使用的您的AppWidgetProvider类的实现(参见在上述清单声明的⼀个AppWidget)。
appwidgetprovider作为⼀个方便的类来继承broadcastreceiver处理App widget广播。 AppWidgetProvider接收事件广播,如App widget进行更新时,相关的App widget进行删除,启用和禁用。这些广播事件发生
时,AppWidgetProvider将调用以下的方法:
onUpdate()
这种在AppWidgetProviderInfo由updatePeriodMillis属性定义的时间间隔叫做AppWidget更新。(请参阅上面添加AppWidgetProviderInfo元数据)这种方法也被称为用户添加App widget,所以它应该进行必要的设置,如视图定义事件处理程序,如果有必要,应启动临时服务。不过,如果你已经宣布配置的Activity,这种方法则不叫用户添加App widget,而是后续更新调用。配置的Activity完成后,它的作用就是执行第⼀次更新。
(参见下面创建⼀个AppWidget配置的Activity。)
onDeleted(Context, int[])
⼀个App Widget从App Widget主机中删除。
onEnabled(Context)
首次创建当⼀个实例App widget。例如,如果用户添加了两个实例App widget,这也只能称为第⼀次创建。如果
你需要打开⼀个新的数据库或进行其他的设置,只需要执行⼀次App widget实例,那么在这个地方实例是非常好的。
onDisabled(Context)
这是最后⼀个实例时调用App widget,从应用程序中删除主机中的App widget。使用onDisabled(Context)方法进行清理,比如删除临时数据库。
onReceive(Context, Intent)
这是呼吁每个广播之前,上面的每个回调方法。你通常不需要实现这个方法,因为默认的AppWidgetProvider实现过滤器所有App widget广播,并适当调用上面的方法。
注:在Android1.5中,有⼀个已知的问题,就是onDeleted()方法将不会被调用。为解决此问题,您可以实
现onDeleted()方法的回调。
当每个App widget添加到⼀个主机时,最重要的是AppWidgetProvider onUpdate()方法回调(除非你使用⼀个配置的Activity)。如果你的App widget接受任何用户交互事件,在回调时,你需要注册事件来处
理程序。如果你的App widget不能创建临时文件或数据库,或者执行其他的⼯作,需要清理,您需要定义onUpdate()方法,它可能是唯⼀的回调方法。例如,如果你想要⼀个App widget窗⼝按钮,当点击时启动⼀个Activity,你可以使用以下实现的AppWidgetProvider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds){ final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for(int i=0; i<N; i++){
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent =new Intent(context, ExampleActivity.class);
PendingIntent pendingIntent = Activity(context,0, intent,0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views =new PackageName(), R.layout.appwidget_provider_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
这appwidgetprovider只定义onupdate()方法,其目的是定义⼀个pendingintent启动⼀个Activity和附加到App widget使用setonclickpendingintent(int,pendingintent)方法的按钮。注意,在updateperiod
millis时间表将管理所有的App widget。例如,如果更新计划被定义为每两个⼩时,在第⼀个后添加第⼆个实例的App widget并每⼩时更新⼀次,那么它们都将被定义为第⼀个而第⼆个更新周期会被忽略(他们会每两⼩时更新,而不是每隔⼀⼩时)。
注:由于AppWidgetProvider是继承BroadcastReceiver,不能保证你的进程保持运行后的回调方法的返回(见BroadcastReceiver广播周期的信息)。如果您的App widget设置过程可能要花费⼏秒(也许同时执行Web请求),并且要求你的进程仍在继续,可以考虑在OnUpdate()方法中启动⼀个Service。从内的服务,您可以执行更新自⼰的App widget,不用担心由于AppWidgetProvider关闭应用程序而出现"Application Not Responding"的(ANR)错误。参看Wiktionary sample's AppWidgetProvider⼀个App widget使用后台服务的示例。
也参考ExampleAppWidgetProvider.java的示例类。
Receiving App Widget broadcast Intents
AppWidgetProvider仅仅是⼀个方便的类。如果你想直接接收App widget广播,你可以实现自⼰的BroadcastReceiver或覆盖的onReceive(Context, Intent) 方法。你需要知道以下四个意图:
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
Creating an App Widget Configuration Activity
如果你想设定的用户,当他或她增加了⼀个新的App widget时,你可以创建⼀个App widget配置Activity。当前的Acitivity将自动启动的App widget的主机,并允许用户在创建时配置App widget的颜,⼤⼩,更新周期或其他功能的设置。这个配置的Activity应该在Android manifest文件中声明是⼀个标准的Activity。然而,它将发起这个App widget主机ACTION_APPWIDGET_CONFIGURE的⼀个Action,所以Activity需要接受这种意图。例如:
1 2 3 4 5<activity android:name=".ExampleAppWidgetConfigure">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/> </intent-filter>
</activity>
安卓intent用法此外,Activity必须在AppWidgetProviderInfo XML文件中声明android:configure属性(参见前面添加AppWidgetProviderInfo的元数据)。例如,可配置的Activity声明如下:
1 2 3 4 5<appwidget-provider xmlns:android="schemas.android/apk/res/android"
...
android:configure="ample.android.ExampleAppWidgetConfigure"
...>
</appwidget-provider>
注意,这个Activity是声明完全限定的命名空间,因为它是从包范围之外引用的。
你需要的是开始使用⼀个配置Activity。现在你所需要的是实际的Activity。然而,当你实现Activity有两个重要的事情要记住:
这个App widget主机调用配置Activity,而配置Activity应该总是返回⼀个结果码。这个结果码应该包括App widget ID所通过的意图发起这⼀Activity(这个意图作为EXTRA_APPWIDGET_ID进行额外保存)。
当创建App widget时OnUpdate()方法将不会被调用(配置Activity启动时,系统将不发送
ACTION_APPWIDGET_UPDATE广播)。
这是配置Activity的作用,请求从App widget首次创建AppWidgetManager时更新。然而,onUpdate()方法将呼吁后续更新,它只是跳过第⼀次。
请参阅以下部分中的⼀个例⼦,从配置和更新的App widget的代码片段中如何返回结果。
Updating the App Widget from the configuration Activity
当⼀个App widget使用配置Activity,这个Activity配置完成后负责更新App widget。你可以从appwidgetmanager 通过请求直接更新.
以下总结了正确的更新App widget并关闭该配置Activity:
1.第⼀步,把App widget的ID通过意图发起这⼀Activity:
1 2 3 4 5 6 7Intent intent = getIntent();
Bundle extras = Extras();
if(extras !=null){
mAppWidgetId = Int(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID); }
2.第⼆步,执行你的App widget配置.
3.第三部,当配置完成后,通过调用getInstance(context)获得⼀个实例的AppWidgetManager:
1AppWidgetManager appWidgetManager = Instance(context);
4.第四步,通过调用updateAppWidget(int,RemoteViews)更新App widget与RemoteViews布局:
1 2 3RemoteViews views =new PackageName(), ample_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
5.最后,创建返回的意图,其设置Activity的结果码,并终止该Activity:
1 2 3 4Intent resultValue =new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue);
finish();
提示:当你的配置Activity首次打开时,在该Activity使用RESULT_CANCELED设置结果码。这样,如果用户选择退出之前能够达到目的,App widget通知配置被取消,并不会再添加。
请参见ApiDemos ExampleAppWidgetConfigure.java的示例类。
Setting a Preview Image
Android 3.0引⼊了previewImage字段,它指定⼀个Appwidget预览。这个预览是给用户显示⼩部件的选择器。如果没有提供这个字段,则这个Appwidget的图标只用于预览。
如何在XML中指定此设置:
1 2 3 4<appwidget-provider xmlns:android="schemas.android/apk/res/android"
.
..
android:previewImage="@drawable/preview">
</appwidget-provider>
为了帮助您的Appwidget(指定在previewImage领域)创建预览图像,在Android模拟器中包含⼀个应用程序被称为“⼩⼯具预览”。要创建预览图像,则要启动该应用程序,选择您的应用程序的Appwidget,并设置您希望的预览图像,然后将它保存,并将其放置在您的应用程序的绘制资源。
Using App Widgets with Collections
Android 3.0引⼊了Appwidget集合。这些类型的Appwidget使用RemoteViewsService显示集合,支持了远程数据.比如从⼀个content provider,它所提供的数据RemoteViewsService提出Appwidget通过使用以下视图类型,我们称之为"集合视图."
ListView
⼀个视图来显示项目在⼀个垂直滚动列表项。例如,查看Gmail的Appwidget。 GridView
⼀个视图来显示项目在双向滚动的网格。例如,查看书签的Appwidget。 StackView
⼀堆卡片视图(有点像⼀盒名片), 用户可在其中滑动前插卡上或下看到上⼀张或下⼀张卡.例如,YouTube和书籍的Appwidget。 AdapterViewFlipper
⼀个适配器支持简单的ViewAnimator不会苟同,在两个或多个视图。只有⼀个孩⼦会显示。
如上所述,这些集合视图由远程数据集合进行显示。这意味着他们使用⼀个Adapter以他们的数据来绑定他们的View。⼀个Adapter从⼀组数据为单独的视图对象绑定到个别项目。因为这些集合视图是由Adapter,Android框架必须包括额外的架构来支持他们的使用在Appwidget。⼀个应用程序上下文中的⼩部件,而适配器是⼀个RemoteViewsFactory所取代,这是⼀个简单的瘦包装器的Adapter接⼝。当请求⼀个特定的项目在收集、RemoteViewsFactory创建并返回条目的集合作为⼀个RemoteViews对象。为了将⼀个集合视图在你的Appwidget,您必须实现RemoteViewsService和RemoteViewsFactory。
RemoteViewsService是⼀个服务,允许远程适配器请求RemoteViews对象。
RemoteViewsFactory是⼀个接⼝之间的适配器集合视图(如列ListView,GridView,等等)和底层的数据视图。从StackView Widget sample,下面是⼀个示例样板代码使用来实现这个服务和接⼝:
1 2 3 4 5 6 7 8 9 10 11 12public class StackWidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent){
return new ApplicationContext(), intent);
}
}
class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory{ //... include adapter-like methods here. See the StackView Widget sample.
}
Sample application
这⼀节的代码摘录来自StackView Widget sample:
这个示例包括⼀堆10视图,它显示值"9!"的样例Appwidget,其具有这些主要的行为:
用户可以垂直上抛视图的应用程序窗⼝显示下⼀个或前视图。这是⼀个内置的Stack View行为。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论