Posted by Jeff Sharkey on 20 April 2009 at 6:43 PM
One
exciting new feature in the Android 1.5 SDK is the AppWidget framework
which allows developers to write "widgets" that people can drop onto
their home screen and interact with. Widgets can provide a quick
glimpse into full-featured apps, such as showing upcoming calendar
events, or viewing details about a song playing in the background.
一个比较激动的新功能将会在
Android1.5SDK
中提供,就是
AppWidgetk
框架,这个框架允许开发者在编写
widgets
时提供一个不在主应用程序桌面而与其交互的功能。如显示即将来临的日历事件或者显示后台播放音乐的信息。
When
widgets are dropped onto the home screen, they are given a reserved
space to display custom content provided by your app. Users can also
interact with your app through the widget, for example pausing or
switching music tracks. If you have a background service, you can push
widget updates on your own schedule, or the AppWidget framework
provides an automatic update mechanism.
当
widgets
退出其界面,我们将给一个保留的空间去显示应用程序的自定内容,用户也可以通过它与你的应用程序交互。例如暂停或选择音乐。如果是后台服务,你可以根据自己的计划去更新你的
widget,AppWidget
也提供了一个自动更新的机制。
At
a high level, each widget is a BroadcastReceiver paired with XML
metadata describing the widget details. The AppWidget framework
communicates with your widget through broadcast intents, such as when
it requests an update. Widget updates are built and sent using
在更高的级别,任何
widget
都是一对
BroadcastReceiver
通过
XML
元数据描述
widget
的详细信息。
AppWidget
框架通过广播与你的
widget
通讯。例如当一个请求被更新,
widget
更新将建立。
RemoteViews which package up a layout and content to be shown on the home screen.
信息将会显示在桌面,如下图:
You
can easily add widgets into your existing app, and in this article I'll
walk through a quick example: writing a widget to show the Wiktionary
"Word of the day." The full source code is available
, but I'll point out the AppWidget-specific code in detail here.
你可以很容把这个功能加入你已经有的程序中,在下面的内容中,我们将通过一个例子:写一个
widget
去显示
Wiktionary “Word of he day”
源码可以点英文中的那个
full source code is available
链接,但我需要指出的这个功能的特别处将会在这里讲述。
First, you'll need some XML metadata to describe the widget
,
including the home screen area you'd like to reserve, an initial layout
to show, and how often you'd like to be updated. The default Android
home screen uses a cell-based layout, so it rounds your requested size
up to the next-nearest cell size. This can be a little confusing, so
here's a quick equation to help:
第一步:你需要用
XML
的元数据描述一下
widget.
包括你在桌面保留的区域,初始化一个布局去显示,还有你多久就更新一下其中的内容。
Android
桌面默认的布局是
cell-based.,
你可以申请一个相邻的单元格。在申请时可能有些麻烦,可以通过下面的公式来计算。
Minimum size in dip = (Number of cells * 74dip) - 2dip
In
this example, we want our widget to be 2 cells wide and 1 cell tall,
which means we should request a minimum size 146dip x 72dip. We're also
going to request updates once per day, which is roughly every
86,400,000 milliseconds. Here's what our widget XML metadata looks like:
在这个例子中,我们分别给
widget2
个单元格的宽度和一个单元格的高度,我们应该申请最小的大小为
146dip x 72dip,
我们也将要求每天更新一次。这大概是每八千六百四十〇点〇
〇
〇万毫秒,
XML
的元数据配置如下:
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip"
android:minHeight="72dip"
android:initialLayout="@layout/widget_message"
android:updatePeriodMillis="86400000"
/>
Next, let's pair this XML metadata with a BroadcastReceiver in the AndroidManifest
:
接下来是下一对
BroadcastReceiver in the AndroidManifest
:XML
元数据
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".WordWidget" android:label="@string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_word" />
</receiver>
<!-- Service to perform web API queries -->
<service android:name=".WordWidget$UpdateService" />
Finally,
let's write the BroadcastReceiver code to actually handle AppWidget
requests. To help widgets manage all of the various broadcast events,
there is a helper class called AppWidgetProvider, which we'll use here.
One very important thing to notice is that we're launching a background
service to perform the actual update. This is because
BroadcastReceivers are subject to the Application Not Responding
(ANR) timer, which may prompt users to force close our app if it's
taking too long. Making a web request might take several seconds, so we
use the service to avoid any ANR timeouts.
最后,我们写一下
BroadcastReceiver
代码处理
AppWidget
请求,去帮助
widget
管理所以类型的广播消息。我们需要继承的类名为
AppWidgetProvider
,一个需要注意的是我们需要一个后台程序去执行
widget
的更新,这是因为
BroadcastReceivers
取决于
ANR
时间,它可能关闭我们的程序当它运行时间比较长的时候,一个
WEB
请求可以需要几分钟,所以我们使用后台服务去避免任何的
ANR
超时。
/**
* Define a simple widget that shows the Wiktionary "Word of the day." To build
* an update we spawn a background {@link Service} to perform the API queries.
*/
public class WordWidget extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// To prevent any ANR timeouts, we perform the update in a service
context.startService(new Intent(context, UpdateService.class));
}
public static class UpdateService extends Service {
@Override
public void onStart(Intent intent, int startId) {
// Build the widget update for today
RemoteViews updateViews = buildUpdate(this);
// Push update for this widget to the home screen
ComponentName thisWidget = new ComponentName(this, WordWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
/**
* Build a widget update to show the current Wiktionary
* "Word of the day." Will block until the online API returns.
*/
public RemoteViews buildUpdate(Context context) {
// Pick out month names from resources
Resources res = context.getResources();
String[] monthNames = res.getStringArray(R.array.month_names);
// Find current month and day
Time today = new Time();
today.setToNow();
// Build today's page title, like "Wiktionary:Word of the day/March 21"
String pageName = res.getString(R.string.template_wotd_title,
monthNames[today.month], today.monthDay);
RemoteViews updateViews = null;
String pageContent = "";
try {
// Try querying the Wiktionary API for today's word
SimpleWikiHelper.prepareUserAgent(context);
pageContent = SimpleWikiHelper.getPageContent(pageName, false);
} catch (ApiException e) {
Log.e("WordWidget", "Couldn't contact API", e);
} catch (ParseException e) {
Log.e("WordWidget", "Couldn't parse API response", e);
}
// Use a regular expression to parse out the word and its definition
Pattern pattern = Pattern.compile(SimpleWikiHelper.WORD_OF_DAY_REGEX);
Matcher matcher = pattern.matcher(pageContent);
if (matcher.find()) {
// Build an update that holds the updated widget contents
updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_word);
String wordTitle = matcher.group(1);
updateViews.setTextViewText(R.id.word_title, wordTitle);
updateViews.setTextViewText(R.id.word_type, matcher.group(2));
updateViews.setTextViewText(R.id.definition, matcher.group(3).trim());
// When user clicks on widget, launch to Wiktionary definition page
String definePage = res.getString(R.string.template_define_url,
Uri.encode(wordTitle));
Intent defineIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(definePage));
PendingIntent pendingIntent = PendingIntent.getActivity(context,
0 /* no requestCode */, defineIntent, 0 /* no flags */);
updateViews.setOnClickPendingIntent(R.id.widget, pendingIntent);
} else {
// Didn't find word of day, so show error message
updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_message);
CharSequence errorMessage = context.getText(R.string.widget_error);
updateViews.setTextViewText(R.id.message, errorMessage);
}
return updateViews;
}
@Override
public IBinder onBind(Intent intent) {
// We don't need to bind to this service
return null;
}
}
}
And
there you have it, a simple widget that will show the Wiktionary "Word
of the day." When an update is requested, we read the online API and
push the newest data to the surface. The AppWidget framework
automatically requests updates from us as needed, such as when a new
widget is inserted, and again each day to load the new "Word of the
day."
到现在你已经完成了,一个简单的显示
Wiktionary”Word of the day”
的
widget
,当有一个更新请求,我们使用在线
API
推送新的数据给他。
AppWidget
框架的自动更新机制可以满足我们的需求。例如当一个新的
widget
插入,每天再次加载
”Word of the day”
Finally,
some words of wisdom. Widgets are designed for longer-term content that
doesn't update very often, and updating more frequently than every hour
can quickly eat up battery and bandwidth. Consider updating as
infrequently as possible, or letting your users pick a custom update
frequency. For example, some people might want a stock ticker to update
every 15 minutes, or maybe only four times a day. I'll be talking about
additional strategies for saving battery life as part of a session I'm giving at Google I/O
.
One
last cool thing to mention is that the AppWidget framework is
abstracted in both directions, meaning alternative home screens can
also contain widgets. Your widgets can be inserted into any home screen
that supports the AppWidget framework.
最后一个很酷的事情提的是
AppWidget
框架在两个方向都是抽象的。意思是你可以任选其一,是桌面包含
widgets ,,
你的
widget
也可以插入一个桌面。这些都是
AppWidget
框架所支持的。
We've
already written several widgets ourselves, such as the Calendar and
Music widgets, but we're even more excited to see the widgets you'll
write!
我已经写好了一些
widget
,例如日历,音乐,但我们更高兴看到你写的。
分享到:
相关推荐
Introducing Home Screen Widgets Creating App Widgets Creating an Earthquake Widget Introducing Collection View Widgets Introducing Live Folders Surfacing Application Search Results Using the Quick ...
Home Screen App Widgets Adapter-Based App Widgets Publishing Slices Hosting Slices Advanced Permissions Restricted Profiles and UserManager Device Authentication Keys and the Keystore Miscellaneous ...
Home Screen App Widgets Adapter-Based App Widgets Content Provider Theory Content Provider Implementation Patterns The Loader Framework The ContactsContract and CallLog Providers The CalendarContract ...
Introducing the Cloud App Model.pptx
Introducing InnoDB Cluster teaches you about the building blocks that make up InnoDB Cluster such as MySQL Group Replication for storing data redundantly, MySQL Router for the routing of inbound ...
The name is a pun, but where the humor might be atrocious, the language is not. The Markdown language lets you write plain text documents with a few lightweight annotations that specify how you want ...
Introducing ZFS on Linux Understand the Basics of Storage with ZFS 英文无水印原版pdf pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本资源转载自网络,如有侵权,请...
This book is an introduction to the well-known Spring Framework that offers an inversion of control container for the Java platform....• Use the new Spring Boot and Spring XD technologies.
Introducing Regular Expressions JavaScript and TypeScript 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
The book starts by introducing the Android development environment and exploring the support libraries. You will gradually explore the different design and layout patterns and get to know the best ...
Introducing ZFS on Linux Understand the Basics of Storage with ZFS 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
This new 7th edition of Pro C# 6.0 and the .NET 4.6 Platform has been completely revised and rewritten to reflect the latest changes to the C# language specification and new advances in the .NET ...
Introducing the MySQL 8 Document Store presents new tools and features that make creating a hybrid database solution far easier than ever before. This book covers the vitally important MySQL Document ...
Introducing Regular Expressions JavaScript and TypeScript 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载...
【船级社】 NK Guidelines for Introducing Health, Safety and Environmental Management System.pdf