Widget是一种小巧但是功能强大的程序,使用户能够方便快捷的获取信息,在PC上被广泛的使用,现在随着OPhone的推出,widget也进入到了手机领域,为用户带来了方便的同时也为开发者实现更多很酷想法的可能。在OPhone中有两种widget开发方式,一种是以HTML+CSS+JavaScript的开发方式,另一种是沿用Android平台的开发方式,本文介绍的是后面一种,在OPhone平台上开发App widget。
widget一般开发方式介绍
下面以编写一个时钟的小程序来介绍如何编写widget。
(1)创建一个类,让其继承类AppWidgetProvider,在AppWidgetProvider类中有许多的方法,例如onDelete(Context, int[]),onEnable(Context)等等,一般情况下我们纸需要重写onUpdate(Context, AppWidgetManager, int[])这个方法就可以了,这个方法是当触发器更新widget时候执行的操作。
(2)在项目的AndroidMenifest.xml文件中添加一个receiver标签,让其指向前面创建的AppWidgetProvider子类,内容如下:
01.<receiver android:name="widget"
02. android:label="@string/app_name"
03. android:icon="@drawable/icon">
04. <intent-filter>
05. <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
06. </intent-filter>
07. <meta-data android:name="android.appwidget.provider"
08. android:resource="@xml/widget_setting" />
09. </receiver>
intent-filter中过滤了APPWIDGET_UPDATE事件,这个事件是由系统触发的更新事件,每个widget必须包含这个事件;meta-data标签描述的是widget的配置文件指向,该文件描述了widget的一些基本信息。
(3)编写widget的provider文件信息,本例中该文件名叫做widget_setting.xml,开发者可以随便取名,只要在AndroidMenifest.xml中写正确就行。
01.<?xml version="1.0" encoding="utf-8"?>
02.<appwidget-provider
03. xmlns:android="http://schemas.android.com/apk/res/android"
04. android:minWidth="100dp"
05. android:minHeight="100dp"
06. android:initialLayout="@layout/main"
07. android:updatePeriodMillis="1000" >
08.</appwidget-provider>
minWidth和minHeight是widget的最小宽度和高度,这个值是一个参考值,系统会根据实际情况进行改变,initialLayout属性指明了widget的视图布局文件,updatePeriodMillis属性是widget每隔多久更新一次的时间,单位为毫秒。
(4)接下来就是界面布局,在这个示例中只需要一个TextView控件就可以,代码如下:
01.<?xml version="1.0" encoding="utf-8"?>
02.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03. android:orientation="vertical"
04. android:layout_width="fill_parent"
05. android:layout_height="fill_parent"
06. >
07.<TextView
08. android:layout_width="fill_parent"
09. android:layout_height="wrap_content"
10. android:text="@string/hello" android:id="@+id/text"/>
11.</LinearLayout>
准备工作完毕,接下来完善继承自AppWidgetProvider的自定义类,重写onUpdate(Context, AppWidgetManager,int[])函数,代码如下:
01.package com.dt.time;
02.
03.import java.util.Date;
04.
05.import android.appwidget.AppWidgetManager;
06.import android.appwidget.AppWidgetProvider;
07.import android.content.Context;
08.import android.widget.RemoteViews;
09.
10.public class widget extends AppWidgetProvider {
11.
12. @Override
13. public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
14. // TODO Auto-generated method stub
15. super.onUpdate(context, appWidgetManager, appWidgetIds);
16.
17. //1. 获取当前时间
18. Date now = new Date();
19. String strNow = now.toLocaleString();
20. //2. 获取RemoteViews对象
21. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
22. //3. 显示时间到widget
23. views.setTextViewText(R.id.text, strNow);
24. //4. 更新widget
25. appWidgetManager.updateAppWidget(appWidgetIds, views);
26. }
27.}
package com.dt.time; import java.util.Date; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.widget.RemoteViews; public class widget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // TODO Auto-generated method stub super.onUpdate(context, appWidgetManager, appWidgetIds); //1. 获取当前时间 Date now = new Date(); String strNow = now.toLocaleString(); //2. 获取RemoteViews对象 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main); //3. 显示时间到widget views.setTextViewText(R.id.text, strNow); //4. 更新widget appWidgetManager.updateAppWidget(appWidgetIds, views); } }
之后运行写好的widget查看下成果,widget的启动与普通程序不同,它不会在程序列表中显示,而是要长按桌面在弹出的列表中选择Widgets项目,之后选择本示例time,下图就是widget运行时的截图:
widget的扩展更新方法
在上例中widget更新是通过定时方式实现的,在普通情况下这种更新方式已经足够了,但是对于某些应用使用定时方式更新显得就不够用了。比如短信提示,当有新的短信到来时我们希望能够实时的更新widget,如果还是用定时更新显然是不行的,那么能不能让widget接受除appwidget_update之外的系统消息呢?答案是可以的。
仔细查看下文档后可以发现,widget只是一个receiver,既然是receiver那么也就可以接受所有的系统消息了,接下来使用短信提醒示例来演示widget接受系统其他消息的方式,本例中将只前一示例进行修改。
(1)修改AndroidMenifest.xml文件,向其中添加android.provider.Telephony.SMS_RECEIVED监听事件,代码如下:
01.<receiver android:name=".widget" >
02. <intent-filter>
03. <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
04. <action android:name="android.provider.Telephony.SMS_RECEIVED" />
05. </intent-filter>
06. <meta-data android:name="android.appwidget.provider"
07. android:resource="@xml/widget_provider" />
08.</receiver>
<receiver android:name=".widget" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider" /> </receiver>
添加了这个短信监听事件后,我们就已经向widget添加了监听短信的功能了,实际操作非常简单。
接下来需要添加一个阅读短信的权限,在AndroidMenifest.xml中任意位置添加<uses-permission android:name="android.permission.RECEIVE_SMS" />
(2)然后还需要修改下widget_setting.xml文件,将其中的updatePeriodMillis属性设为0,也就是不定时更新,这样可以展示这个widget是实时更新的。
(3)之后修改AppWidgetProvider的子类,使其将短信内容显示到widget上。在本示例中我们将不再修改onUpdate(Context, AppWidgetManager,int[])函数,而是重写onReceive(Context context, Intent intent)函数,这个函数其实能够实现包括onUpdate在内的所有函数功能,代码如下:
01.package com.dt.time;
02.
03.import android.appwidget.AppWidgetManager;
04.import android.appwidget.AppWidgetProvider;
05.import android.content.ComponentName;
06.import android.content.Context;
07.import android.content.Intent;
08.import android.widget.RemoteViews;
09.
10.public class widget extends AppWidgetProvider {
11.
12. @Override
13. public void onReceive(Context context, Intent intent) {
14. // TODO Auto-generated method stub
15. super.onReceive(context, intent);
16.
17. //1. 获取RemoteViews对象
18. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
19. //2. 显示新消息提醒
20. views.setTextViewText(R.id.text, "New message!");
21. //3. 更新widget
22. AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
23. appWidgetManager.updateAppWidget(new ComponentName(context, widget.class), views);
24. }
25.}
package com.dt.time; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; public class widget extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub super.onReceive(context, intent); //1. 获取RemoteViews对象 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main); //2. 显示新消息提醒 views.setTextViewText(R.id.text, "New message!"); //3. 更新widget AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.updateAppWidget(new ComponentName(context, widget.class), views); } }
代码与上一示例差别不多,唯一有区别的地方便是appWidgetManager的实例化,在上一示例中由于onUpdate()方法中有一个参数是appWidgetManager因此我们不需要单独实例化该对象,但是在onReceive()方法中并没有这个参数,因此我们需要实例化一个appWidgetManager,通过AppWidgetManager.getInstance(Context)方法就可以获得一个appWidgetManager实例。当然由于onReceive()函数还缺少appWidgetIds这个参数,因此我们也不能直接使用updateAppWidget(int[] appWidgetIds, RemoteViews views)这个函数,而要改用updateAppWidget(ComponentName provider, RemoteViews views)这个函数,其中provider参数是一个ComponentName类型的值,简单的说就是组件名,通过实例化一个组件便可;第二个参数是是一个视图对象,就是想要展示的widget视图。
通过这样简单的改动,当有新的短信息发到手机上时就能第一时间展示在widget中,做到了实时更新。
widget的进阶更新方法
上面的示例已经让widget可以实时的更新内容,但是如果要显示电池电量的话,上面的方法还是不行的,为什么呢?原来android中并没有为获取电池信息设计单独的api,必须注册为一个service才能获取。按照上面的思路那也简单,只要我们写个service,然后在系统中广播更新消息就可以了;但是根据文档中的说明,要获取电池信息的service必须是通过Context.registerReceiver()这个函数来注册一个监听电池变化的事件才能获取,这样一来对我们设计就带来了麻烦。
解决的方法倒也很简单,就是单独写个service在里面注册一个监听事件,当电池电量发生变化的时候就更新widget,看起来与我们上面的例子很相似,就是多了一个service,但是这里还有一个不同的是,我们更新widget的方法不再是在onUpdate()或者是onReceive中进行,而是在service中直接对widget修改,似乎跟文档上说的出入很大,但是看看上面显示短信的例子我们会发现,在那个示例中似乎widget的更新与appWidgetProvider已经没有什么关系了,我们即没有从参数获得appWidgetManager实例,也没从参数中获得appWidgetIds,一切都是我们自己新建了一个,因而不再widget更新的方法完全是可行的。下面来介绍下代码:
(1)本示例中沿用第二个示例的代码,添加一个名叫service.java类
view plaincopy to clipboardprint?
01.package com.dt.time;
02.
03.import android.app.Service;
04.import android.appwidget.AppWidgetManager;
05.import android.content.BroadcastReceiver;
06.import android.content.ComponentName;
07.import android.content.Context;
08.import android.content.Intent;
09.import android.content.IntentFilter;
10.import android.graphics.Color;
11.import android.os.IBinder;
12.import android.widget.RemoteViews;
13.
14.public class mService extends Service {
15.
16.
17. @Override
18. public void onStart(Intent intent, int startId) {
19. // TODO Auto-generated method stub
20. super.onStart(intent, startId);
21. registerReceiver(this.mBR, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
22.
23. }
24.
25. //声明一个广播接受对象,用接受电池信息
26. private BroadcastReceiver mBR = new BroadcastReceiver() {
27.
28. @Override
29. public void onReceive(Context context, Intent intent) {
30. // TODO Auto-generated method stub
31.
32. if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction()))
33. {
34. //这里添加相关处理动作
35. bLevel = intent.getIntExtra("level", 0); //获取当前电量
36.
37. String value = String.valueOf(bLevel) + "%"; //显示电量的文字
38.
39. AppWidgetManager awm = AppWidgetManager.getInstance(context);
40. RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.main);
41.
42. views.setTextViewText(R.id.text, value);
43.
44. awm.updateAppWidget(new ComponentName(context, widget.class), views);
45. }
46. }
47. };
48.}
package com.dt.time; import android.app.Service; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.os.IBinder; import android.widget.RemoteViews; public class mService extends Service { @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); registerReceiver(this.mBR, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); } //声明一个广播接受对象,用接受电池信息 private BroadcastReceiver mBR = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { //这里添加相关处理动作 bLevel = intent.getIntExtra("level", 0); //获取当前电量 String value = String.valueOf(bLevel) + "%"; //显示电量的文字 AppWidgetManager awm = AppWidgetManager.getInstance(context); RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.main); views.setTextViewText(R.id.text, value); awm.updateAppWidget(new ComponentName(context, widget.class), views); } } }; }
(2)修改AndroidMenifest.xml文件,向其中添加一个<service android:name=".service"/>,这样就注册了一个系统服务,当widget启动的时候这个服务也会跟着启动,而当widget删除的时候是否也会自动删除呢?经过试验大多数情况下OPhone会自动删除这个service,如果你为了安全也可以手动删除。
之后就可以运行看看效果了,这里展示的截图是我作的一个显示电池电量的widget,目前除了能够显示电量外还添加了其他信息的显示。
- 大小: 33.2 KB
- 大小: 50.1 KB
- 大小: 41.5 KB
分享到:
相关推荐
2. **onUpdate()方法源码**: 在这个方法中,通常你会遍历所有需要更新的AppWidget实例,为每个实例创建新的RemoteViews对象,并调用`appWidgetManager.updateAppWidget(appWidgetIds, remoteViews)`来更新界面。...
`RemoteViews`允许开发者创建和更新`appWidget`的内容,而无需直接操作UI线程。`appWidget`的配置和交互通常通过`BroadcastReceiver`进行,当用户与`appWidget`交互时,如点击它,`BroadcastReceiver`会接收到相应的...
当用户从主屏幕选择添加AppWidget时,系统会调用AppWidgetManager的addAppWidget()方法,随后触发WidgetProvider的onEnabled()和onUpdate()方法。在此过程中,WidgetProvider会创建并配置RemoteViews,然后将它们...
6. **更新AppWidget**: 使用`AppWidgetManager`的`updateAppWidget()`方法可以手动或响应事件更新AppWidget。通常,你会在`AppWidgetProvider`的`onReceive()`方法中调用这个方法,并传递AppWidget的ID和新的布局。 ...
App Widget 的概念 一个简单的App Widget例子 PendingIntent的使用 RemoteViews的使用 接收来自App Widget的广播 更新App Widget的控件状态
AppWidget提供者是Android的BroadcastReceiver子类,它负责处理AppWidget的生命周期事件,如添加、删除或更新。布局文件则定义了AppWidget在主屏幕上的显示样式,通常包含一个或多个远程视图(RemoteViews)。 创建...
9. **更新AppWidget**: Service完成任务后,可能需要更新AppWidget的状态。这时,可以通过`AppWidgetManager`的`updateAppWidget()`方法来更新小部件的视图。 总结来说,AppWidget启动Service是一种常见的Android...
5. **更新AppWidget**:最后,使用`AppWidgetManager`的`updateAppWidget()`方法来更新小部件,以显示ListView。 源码分析: - `RemoteViews`类:它是AppWidget与主应用进程通信的关键,允许我们在不直接访问用户...
本文将深入探讨AppWidget的相关知识点,并通过一个实际的AppWidgetProviderDemo4.28来展示其工作原理和实现方法。 首先,我们要了解AppWidget的基本结构。一个AppWidget由以下几个主要部分组成: 1. **...
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> android:name="android.appwidget.provider" android:resource="@xml/app_widget_info" /> ``` 最后,为了让用户能够添加你的App ...
4. **更新机制**: AppWidget的内容可以通过AppWidgetProviderInfo配置的`updatePeriodMillis`属性定期自动更新,或者通过PendingIntent触发手动更新。此外,还可以在接收到特定广播事件(如系统启动、时间变更等)时...
这是一个继承自`AppWidgetProvider`的类,负责处理广播事件,如AppWidget的添加、更新或删除。例如: ```java public class AppWidgetProvider extends android.appwidget.AppWidgetProvider { @Override public...
在"appwidget"这个压缩包文件中,可能包含了示例代码和资源文件,供开发者学习如何实现上述功能。通过研究这些文件,你可以更好地理解App Widget的工作原理和实现细节,从而在自己的项目中创建出富有特色的桌面小...
3. **更新AppWidget**: 最后,我们需要将这些更改推送到系统,以便更新AppWidget: ```java AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.updateAppWidget...
6. **BroadcastReceiver**: 当AppWidget需要更新或执行其他操作时,AppWidgetProvider会通过BroadcastReceiver接收并处理ACTION_APPWIDGET_UPDATE等广播。 7. **配置Activity (可选)**: 对于需要用户自定义设置的小...
1. **AppWidget提供者(AppWidget Provider)**:这是定义AppWidget行为的组件,负责处理与AppWidget相关的广播事件,如添加、删除或更新小部件。 2. **布局文件(Layout)**:定义了小部件在主屏幕上的外观。可以...
本文将详细介绍Android AppWidget的使用方法,并提供一个示例程序来帮助理解。 首先,AppWidget的构成主要包含以下几个部分: 1. **AppWidgetProvider**: 这是Android的BroadcastReceiver子类,用于接收和处理与...
在本例中,我们关注的是一个特定类型的AppWidget,它显示时间并每秒更新一次。创建这样一个实时更新的时钟AppWidget涉及到多个关键知识点。 首先,我们需要了解`AppWidgetProvider`。它是AppWidget的主要组件,类似...
本节内容就简单的介绍下实现这种功能所用到的appwidget技术,通过3个例子由浅入深来学会使用它。参考资料是mars的教程。 自己实现一个AppWidget的步骤如下: 1. 在src目录下新建一个名为xml的文件夹,在该文件夹下...
3. **实现AppWidget提供者**:创建一个继承自`AppWidgetProvider`的类,重写`onUpdate()`、`onDeleted()`、`onEnabled()`等方法,这些方法会在特定事件触发时调用,比如用户添加或删除小部件时。 4. **更新小部件**...