Android桌面小部件AppWidget

本文的代码实现的功能:假设桌面小部件只包含一个Button和一个TextView,当点击Button后,后台启动一个服务(IntentService实现),该服务每个一秒发送一个简单的字符串消息数据data,然后将此消息数据更新到桌面小部件的TextView里面实时显示。

这次,在Androidmanifest.xml有关receiver的定义中,与附录文章1相比,将增加一个action:action_update。本例中,Button的按击事件将触发后台启动服务,后台服务Service每隔一秒制造一个简单字符串数据,然后将此数据实时的以广播形式发给AppWidge,AppWidge收到后,就更新到桌面小部件的TextView里面。

(1)定义AppWidget。

先在Androidmanifest.xml里面定义APP widget的,以Android广播形式:

[html]view plaincopy

android:name="android.appwidget.provider"

android:resource="@xml/appwidget"/>

两个用于广播接收的action:action_button和action_update,其中action_button用于在桌面小部件接收用户的点击事件,此action_button将随即启动后台服务,而后台启动的服务将发送广播数据,数据中的广播过滤器即是: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代码实现窗口小部件。

核心的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);

}

// 点击了按钮,开始启动一个后台服务

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首次创建调用

*/

@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="启动后台服务">

android:id="@+id/text"

android:text="text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

(3)后台服务Service。

MyService.java代码文件,此service是一个Android IntentService,具体实现也可以是Service。此service功能简单,是有桌面小部件的button按钮触发,然后在后台启动,启动后在一个for循环里面循环产生一个简单的字符串数据通过广播形式广播出去,注意打进去的广播过滤器是: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注册到Androidmanifest.xml里面:

[html]view plaincopy

(4)公共变量的定义(次要)。

因为涉及到众多公共变量的写入和读出,所以定义了一个单独的Constants.java代码类,专门定义公共的变量定义:

[java]view plaincopy

packagezhangphil.widget;

publicclassConstants {

publicstaticfinalString ACTION_BUTTON ="action_button";

publicstaticfinalString ACTION_UPDATE ="action_update";

publicstaticfinalString KEY_DATA ="data";

}

(5)完整的代码结构。

如图所示:

Android桌面小部件AppWidget_第1张图片

最终,代码运行结果如图所示:

Android桌面小部件AppWidget_第2张图片


http://blog.csdn.net/zhangphil/article/details/50461944

你可能感兴趣的:(Android桌面小部件AppWidget)