本文的代碼實(shí)現(xiàn)的功能:假設(shè)桌面小部件只包含一個(gè)Button和一個(gè)TextView,當(dāng)點(diǎn)擊Button后,后臺(tái)啟動(dòng)一個(gè)服務(wù)(IntentService實(shí)現(xiàn)),該服務(wù)每個(gè)一秒發(fā)送一個(gè)簡(jiǎn)單的字符串消息數(shù)據(jù)data,然后將此消息數(shù)據(jù)更新到桌面小部件的TextView里面實(shí)時(shí)顯示。
這次,在Androidmanifest.xml有關(guān)receiver的定義中,與附錄文章1相比,將增加一個(gè)action:action_update。本例中,Button的按擊事件將觸發(fā)后臺(tái)啟動(dòng)服務(wù),后臺(tái)服務(wù)Service每隔一秒制造一個(gè)簡(jiǎn)單字符串?dāng)?shù)據(jù),然后將此數(shù)據(jù)實(shí)時(shí)的以廣播形式發(fā)給AppWidge,AppWidge收到后,就更新到桌面小部件的TextView里面。
(1)定義AppWidget。
先在Androidmanifest.xml里面定義APP widget的,以Android廣播形式:
[html]view plaincopy
android:name="android.appwidget.provider"
android:resource="@xml/appwidget"/>
兩個(gè)用于廣播接收的action:action_button和action_update,其中action_button用于在桌面小部件接收用戶的點(diǎn)擊事件,此action_button將隨即啟動(dòng)后臺(tái)服務(wù),而后臺(tái)啟動(dòng)的服務(wù)將發(fā)送廣播數(shù)據(jù),數(shù)據(jù)中的廣播過(guò)濾器即是:action_update。
涉及到的res/xml目錄下的appwidget.xml代碼文件:
[html]view plaincopy
android:initialLayout="@layout/appwidget_layout"
android:minHeight="20dip"
android:minWidth="300dip"
android:previewImage="@drawable/ic_launcher"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen">
(2)上次Java代碼實(shí)現(xiàn)窗口小部件。
核心的AppWidget.java代碼:
[java]view plaincopy
packagezhangphil.widget;
importandroid.app.PendingIntent;
importandroid.appwidget.AppWidgetManager;
importandroid.appwidget.AppWidgetProvider;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.util.Log;
importandroid.widget.RemoteViews;
publicclassAppWidgetextendsAppWidgetProvider?{
@Override
publicvoidonReceive(Context?context,?Intent?intent)?{
super.onReceive(context,?intent);
Log.d(this.getClass().getName(),"onReceive");
if(intent?==null)
return;
String?action?=?intent.getAction();
if(action.equals(Constants.ACTION_UPDATE))?{
String?data?=?intent.getStringExtra(Constants.KEY_DATA);
Log.d(Constants.KEY_DATA,?data);
RemoteViews?remoteViews?=newRemoteViews(context.getPackageName(),?R.layout.appwidget_layout);
remoteViews.setTextViewText(R.id.text,?data);
AppWidgetManager?appWidgetManager?=?AppWidgetManager.getInstance(context);
ComponentName?componentName?=newComponentName(context,?AppWidget.class);
appWidgetManager.updateAppWidget(componentName,?remoteViews);
}
//?點(diǎn)擊了按鈕,開(kāi)始啟動(dòng)一個(gè)后臺(tái)服務(wù)
if(action.equals(Constants.ACTION_BUTTON))?{
Intent?serviceIntent?=newIntent(context,?MyService.class);
context.startService(serviceIntent);
}
}
@Override
publicvoidonUpdate(Context?context,?AppWidgetManager?appWidgetManager,int[]?appWidgetIds)?{
Log.d(this.getClass().getName(),"onUpdate");
Intent?intent?=newIntent(Constants.ACTION_BUTTON);
PendingIntent?pendingIntent?=?PendingIntent.getBroadcast(context,0,?intent,0);
//?小部件在Launcher桌面的布局
RemoteViews?remoteViews?=newRemoteViews(context.getPackageName(),?R.layout.appwidget_layout);
//?事件
remoteViews.setOnClickPendingIntent(R.id.btn,?pendingIntent);
//?更新AppWidget
appWidgetManager.updateAppWidget(appWidgetIds,?remoteViews);
}
/**
*?刪除AppWidget
*/
@Override
publicvoidonDeleted(Context?context,int[]?appWidgetIds)?{
super.onDeleted(context,?appWidgetIds);
Log.d(this.getClass().getName(),"onDeleted");
}
@Override
publicvoidonDisabled(Context?context)?{
super.onDisabled(context);
Log.d(this.getClass().getName(),"onDisabled");
}
/**
*?AppWidget首次創(chuàng)建調(diào)用
*/
@Override
publicvoidonEnabled(Context?context)?{
super.onEnabled(context);
Log.d(this.getClass().getName(),"onEnabled");
}
}
RemoteViews用到的appwidget_layout.xml,appwidget_layout.xml即是桌面小部件的布局文件:
[html]view plaincopy
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#33000000">
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="啟動(dòng)后臺(tái)服務(wù)">
android:id="@+id/text"
android:text="text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
(3)后臺(tái)服務(wù)Service。
MyService.java代碼文件,此service是一個(gè)Android IntentService,具體實(shí)現(xiàn)也可以是Service。此service功能簡(jiǎn)單,是有桌面小部件的button按鈕觸發(fā),然后在后臺(tái)啟動(dòng),啟動(dòng)后在一個(gè)for循環(huán)里面循環(huán)產(chǎn)生一個(gè)簡(jiǎn)單的字符串?dāng)?shù)據(jù)通過(guò)廣播形式廣播出去,注意打進(jìn)去的廣播過(guò)濾器是:action_update。
[java]view plaincopy
packagezhangphil.widget;
importandroid.app.IntentService;
importandroid.content.Intent;
publicclassMyServiceextendsIntentService?{
privatestaticintID?=0;
publicMyService()?{
super("ZhangPhilService");
}
@Override
publicintonStartCommand(Intent?intent,intflags,intstartId)?{
returnsuper.onStartCommand(intent,?flags,?startId);
}
@Override
protectedvoidonHandleIntent(Intent?intent)?{
myLongTimeTask(ID++);
}
privatevoidmyLongTimeTask(intid)?{
for(inti?=0;?i?<5;?i++)?{
Intent?intent?=newIntent(Constants.ACTION_UPDATE);
intent.putExtra(Constants.KEY_DATA,"Zhang?Phil?@?CSDN?"+?id?+":"+?i);
sendBroadcast(intent);
try{
Thread.sleep(1000);
}catch(InterruptedException?e)?{
e.printStackTrace();
}
}
}
}
記得要將此service注冊(cè)到Androidmanifest.xml里面:
[html]view plaincopy
(4)公共變量的定義(次要)。
因?yàn)樯婕暗奖姸喙沧兞康膶懭牒妥x出,所以定義了一個(gè)單獨(dú)的Constants.java代碼類,專門定義公共的變量定義:
[java]view plaincopy
packagezhangphil.widget;
publicclassConstants?{
publicstaticfinalString?ACTION_BUTTON?="action_button";
publicstaticfinalString?ACTION_UPDATE?="action_update";
publicstaticfinalString?KEY_DATA?="data";
}
(5)完整的代碼結(jié)構(gòu)。
如圖所示:
最終,代碼運(yùn)行結(jié)果如圖所示:
http://blog.csdn.net/zhangphil/article/details/50461944