`
whotodo
  • 浏览: 168625 次
文章分类
社区版块
存档分类
最新评论

android桌面组件AppWidget

 
阅读更多

====================================================

http://blog.csdn.net/meshless/article/details/6941499

===================================================

前几天学习下了桌面组件开发,现将学习心得跟大家交流下,欢迎探讨!

一、 概述

要进行桌面组件Widget开发,首先要了解AppWidget框架结构。AppWidget是Android 1.5平台推出的一种崭新的应用程序框架。基于AppWidget框架,开发人员可以在OPhone及模拟器上开发形似传统widget的小应用程序,并将其嵌入到其他应用中。

二、AppWidet框架

1、AppWidgetProvider:继承自 BroadcastRecevier , 在AppWidget 应用 update、enable、disable 和 delete 时接收通知。其中,onUpdate、onReceive 是最常用到的方法,它们接收更新通知。 下面对AppWidgetProvider类常用到的方法进行介绍:

(1)onDeleted(Context context, int[]appWidgetIds)

(2)onDisabled(Context context)

(3)onEnabled(Context context)

(4)onReceive(Context context, Intentintent)

Tip:因为 AppWidgetProvider 是继承自BroadcastReceiver 所以可以重写onRecevie 方法,当然必须在后台注册Receiver

(5)onUpdate(Context context,AppWidgetManager appWidgetManager, int[] appWidgetIds)

2、 AppWidgetProvderInfo:描述 AppWidget 的大小、更新频率和初始界面等信息,以XML 文件形式存在于应用的res/xml/目录下。

3、AppWidgetManger :负责管理 AppWidget ,向 AppwidgetProvider 发送通知。 下面对AppWidgetManger 类中主要方法进行介绍:

(1)bindAppWidgetId(int appWidgetId,ComponentName provider)

通过给定的ComponentName 绑定appWidgetId

(2)getAppWidgetIds(ComponentNameprovider)

通过给定的ComponentName 获取AppWidgetId

(3)getAppWidgetInfo(int appWidgetId)

通过AppWidgetId 获取 AppWidget 信息

(4)getInstalledProviders()

返回一个List<AppWidgetProviderInfo>的信息

(5)getInstance(Context context)

获取 AppWidgetManger 实例使用的上下文对象

(6)updateAppWidget(int[] appWidgetIds,RemoteViews views)

通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件

(7)updateAppWidget(ComponentNameprovider, RemoteViews views)

通过 ComponentName 对传进来的 RemoeteView 进行修改,并重新刷新AppWidget 组件

(8)updateAppWidget(int appWidgetId,RemoteViews views)

通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件

4、RemoteViews :一个可以在其他应用进程中运行的类,向 AppWidgetProvider 发送通知。这是构造AppWidet的核心。

三、Widget示例:WidgetDemo

下面改写一个倒计时Demo,该Widget背景图能定时更新。

先看下程序运行效果图:

1、 新建一个Android工程,命名为WidgetDemo

2、 修改string.xml文件如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <resources>
  3. <stringname="hello">HelloWorld,WidgetDemo!</string>
  4. <stringname="app_name">DaysToMay1ST</string>
  5. </resources>


3、 修改main.xml布局文件。

由于Widget是一个实现在桌面的小应用程序,对UI的设计要求高,其中包括大小的计算和界面是否适合屏幕的布局等。所以首先要建立RemoteViews对应的布局文件main.xml。

代码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:background="@drawable/sunset"
  7. >
  8. <TextView
  9. android:id="@+id/may1st"
  10. android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"
  12. android:text="@string/hello"
  13. android:textSize="12px"
  14. android:textColor="#ff0000"
  15. />
  16. </LinearLayout>


4、 建立Widget内容提供者文件。我们在res下建立xml文件夹,并且新建一个widget_provider.xml代码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <appwidget-provider
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:minWidth="50dip"
  5. android:minHeight="50dip"
  6. android:updatePeriodMillis="10000"
  7. android:initialLayout="@layout/main"
  8. >
  9. </appwidget-provider>
5、 修改WidgetDemo.java代码如下:
  1. packagecom.android.rui;
  2. importjava.util.Calendar;
  3. importjava.util.Date;
  4. importjava.util.GregorianCalendar;
  5. importjava.util.Timer;
  6. importjava.util.TimerTask;
  7. importandroid.appwidget.AppWidgetManager;
  8. importandroid.appwidget.AppWidgetProvider;
  9. importandroid.content.ComponentName;
  10. importandroid.content.Context;
  11. importandroid.widget.RemoteViews;
  12. publicclassWidgetDemoextendsAppWidgetProvider{
  13. /**Calledwhentheactivityisfirstcreated.*/
  14. @Override
  15. publicvoidonUpdate(Contextcontext,AppWidgetManagerappWidgetManager,
  16. int[]appWidgetIds){
  17. Timertimer=newTimer();
  18. timer.scheduleAtFixedRate(newMyTime(context,appWidgetManager),1,60000);
  19. super.onUpdate(context,appWidgetManager,appWidgetIds);
  20. }
  21. privateclassMyTimeextendsTimerTask{
  22. RemoteViewsremoteViews;
  23. AppWidgetManagerappWidgetManager;
  24. ComponentNamethisWidget;
  25. publicMyTime(Contextcontext,AppWidgetManagerappWidgetManager){
  26. this.appWidgetManager=appWidgetManager;
  27. switch(Declare.i)//让widget背景图定时变换
  28. {
  29. case1:
  30. remoteViews=newRemoteViews(context.getPackageName(),R.layout.main1);
  31. Declare.i++;
  32. break;
  33. case2:
  34. remoteViews=newRemoteViews(context.getPackageName(),R.layout.main2);
  35. Declare.i++;
  36. break;
  37. case3:
  38. remoteViews=newRemoteViews(context.getPackageName(),R.layout.main3);
  39. Declare.i++;
  40. break;
  41. default:
  42. remoteViews=newRemoteViews(context.getPackageName(),R.layout.main);
  43. Declare.i=0;
  44. Declare.i++;
  45. break;
  46. }
  47. thisWidget=newComponentName(context,WidgetDemo.class);
  48. }
  49. publicvoidrun(){
  50. Datedate=newDate();
  51. Calendarcalendar=newGregorianCalendar(2011,05,01);
  52. longdays=(((calendar.getTimeInMillis()-date.getTime())/1000))/86400-30;
  53. remoteViews.setTextViewText(R.id.may1st,"距离五一假期还有"+days+"天");
  54. appWidgetManager.updateAppWidget(thisWidget,remoteViews);
  55. }
  56. }
  57. }
6、 修改配置文件AndroidManifest.xml文件。

由于使用了reciever和“android.appwidget.action.APPWIDGET_UPDATE”,所以需要在AndroidManifest.xml中进行注册。

代码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.android.rui"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
  7. <receiverandroid:name=".WidgetDemo"
  8. android:label="@string/app_name">
  9. <intent-filter>
  10. <actionandroid:name="android.appwidget.action.APPWIDGET_UPDATE"/>
  11. </intent-filter>
  12. <meta-dataandroid:name="android.appwidget.provider"
  13. android:resource="@xml/widget_provider"
  14. />
  15. </receiver>


四、Widget事件处理

在以上五一假期倒计时的DEMO中只是更新显示了一个界面。在Widget中同样可以通过setOnClickPendingIntent方法来监听一个事件的处理。

比如:当我们点击一个”widget_button”按钮时,会弹出一个Toast提示。主要代码如下:

  1. publicclasswidgetextendsAppWidgetProvider
  2. {
  3. publicvoidonReceive(Contextcontext,Intentintent)
  4. {
  5. super.onReceive(context,intent);
  6. if(intent.getAction().equals("com.android.myapp.widget.CLICK"))
  7. {
  8. Toast.makeText(context,"Itworks!",Toast.LENGTH_SHORT).show();
  9. }
  10. }
  11. publicvoidonUpdate(Contextcontext,AppWidgetManagerappWidgetManager,int[]appWidgetIds){
  12. finalintN=appWidgetIds.length;
  13. for(inti=0;i<N;i++){
  14. intappWidgetId=appWidgetIds[i];
  15. RemotesViewsrv=newRemoteViews(context.getPackageName(),R.layout.main);
  16. IntentintentClick=newIntent("com.android.myapp.widget.CLICK");
  17. PendingIntentpendingIntent=PendingIntent.getBroadcast(context,0,intentClick,0);
  18. rv.setOnClickPendingIntent(R.id.widget_button,pendingIntent);
  19. appWidgetManager.updateAppWidget(appWidgetId,rv);
  20. }
  21. }
  22. }
Tip:"com.android.myapp.widget.CLICK"事件需要在AndroidManifext.xml文件中声明,声明方式同上面的"android.appwidget.action.APPWIDGET_UPDATE"。

五、Widget启动Activity

在Widget中同样可以启动一个Activity,比如Android自带的音乐播放器,当我们添加一个音乐播放器桌面小部件并点击”button”时就开启一个Activity来显示播放音乐的界面。

通过如下代码即可以启动一个Activity:

  1. RemoteViewsrv=newRemoteViews(context.getPackageName(),R.layout.mywidget);
  2. IntentintentActivity=newIntent(context,MusicPlayer.class);
  3. PendingIntentpendingIntentActivity=PendingIntent.getActivity(context,0,intentActivity,0);
  4. rv.setOnClickPendingIntent(R.id.button,pendingIntentActivity);
  5. appWidgetManager.updateAppWidget(appWidgetId,rv);
当我们点击”button”按钮时就可以启动指定的Activity了,代码如下:

  1. context.startActivity(intentActivity);

六、Widget启动Service

Widget还可以启动一个服务。比如Android自带的音乐播放器,要播放音乐肯定需要使用service在后台播放,所以就需要在音乐播放器桌面小部件中启动一个service。使用下面方法可以在Widget中启动一个Service:

  1. RemoteViewsrv=newRemoteViews(context.getPackageName(),R.layout.mywidget);
  2. IntentintentService=newIntent(“Service名”);
  3. context.startService(intentService);
  4. appWidgetManager.updateAppWidget(appWidgetId,rv);

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics