Widget、Timer、TimerTask、Handler、Message的综合使用



每一个Widget实际上就是一个BroadcastReceive,它们通过XML文件来描述Widget的细节。AppWidget框架通过Broadcast intents和Widget通信。Widget在更新组件与普通的android应用程序有些本质的不同。android应用程序在更新组件是会首先获得要更新组件的对象,然后直接对组件更新。而在Widget中并不能直接获得Widget中组件的对象,要想更新组件,必须要使用RemoteViews作为代理来更新Widget中的组件。

下面来看一下开发App Widget的具体步骤。
1.建立一个XML布局文件,在该布局文件中定义在Widget中显示的组件,但要注意,Widget并不支持所有的android组件。只能在Widget中使用如下组件类:
1)用于布局的组件类
FrameLayout
LinearLayout
RelativeLayout
2)用于开发界面的组件类
AnalogClock
Button
Chronometer  计时器
ImageButton
ImageView
ProgressBar

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="280dp"
    android:layout_height="130dp"
    android:background="@drawable/frame"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.clockwidget.MainActivity" >

    <TextView
        android:id="@+id/main_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="30sp"
        android:text="@string/hello_world" />

</RelativeLayout>

2.创建Widget描述文件。该文件时XML格式,必须放在res/xml目录中。基本格式如下:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="300dp"
    android:minHeight="150dp"
    android:initialLayout="@layout/activity_main"   />


3.建立Widget类,该类必须从AppWidgetProvider类继承(AppWidgetProvider是BroadcastReceiver的子类,因此,Widget类可以接收广播消息)。在AppWidgetProvider中定义了几个接收Widget各种事件的方法,其中onUpdate是最常用的方法。在Widget加载时或到了android:updateReriondMillis属性指定的时间,系统会调用onUpdate方法。开发人员可以在该方法中更新Widget中的组件。

for (int i = 0; i < appWidgetIds.length; i++) {
			int appWidgetId=appWidgetIds[i];
			//加载对应的布局类
			RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.activity_main);
			//设置时间转化格式
			SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
			views.setTextViewText(R.id.main_time, sdf.format(new Date()));
			appWidgetManager.updateAppWidget(appWidgetId, views);
		}

其中,for循环,是数据放进去。但是,SDK1.5之后此方法android:updatePeriodMillis就失效了 ,要自己创建service更新。

	Timer timer=new Timer();
	private TimerTask tt=new TimerTask() {
		
		@Override
		public void run() {
			Message message=Message.obtain();
			myHandler.sendMessage(message);
		}
	};
	private Handler myHandler=new Handler(){
		public void handleMessage(android.os.Message msg) {
			Log.d("lhm", "appwidget的长度是"+appWidgetIds.length);
			for (int i = 0; i < appWidgetIds.length; i++) {
				int appWidgetId=appWidgetIds[i];
				//加载对应的布局类
				RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.activity_main);
				//设置时间转化格式
				SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
				views.setTextViewText(R.id.main_time, sdf.format(new Date()));
				appWidgetManager.updateAppWidget(appWidgetId, views);
			}
		};
	};
使用schedule方法
//设置定时器,每隔1s发送
timer.schedule(tt, 0, 1000);

4.这是最后一步,也是最关键的一步。就是在AndroidManifest.xml文件中定义一个receiver,以便系统和Widget进行通信,下面是一个典型的receiver。

 	<receiver
            android:name="com.example.clockwidget.TimerService"
            android:label="MyUsefulClock" >
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/clockwidget" />
            <intent-filter >
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
        </receiver>

整体代码

在drawable-mdpi文件夹添加图片frame.png

时钟布局layout.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="280dp"
    android:layout_height="130dp"
    android:background="@drawable/frame"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.clockwidget.MainActivity" >

    <TextView
        android:id="@+id/main_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="30sp"
        android:textColor="#000000" />

</RelativeLayout>

在res/xml的文件夹添加clockwidget.xml

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="300dp"
    android:minHeight="150dp"
    android:initialLayout="@layout/activity_main" 
    android:previewImage="@drawable/frame" />

在AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.clockwidget"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
         <receiver
            android:name="com.example.clockwidget.TimerService"
            android:label="MyUsefulClock" >
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/clockwidget" />
            <intent-filter >
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>
package com.example.clockwidget;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;

public class TimerService extends AppWidgetProvider {
	private Context context;
	private Timer timer=new Timer();
	private int[] appWidgetIds;
	private AppWidgetManager appWidgetManager;
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		// TODO Auto-generated method stub
		super.onUpdate(context, appWidgetManager, appWidgetIds);
		this.context=context;
		this.appWidgetIds=appWidgetIds;
		this.appWidgetManager=appWidgetManager;
		//设置定时器,每隔1s发送
		timer.schedule(tt, 0, 1000);
	}
	private TimerTask tt=new TimerTask() {
		
		@Override
		public void run() {
			Message message=Message.obtain();
			myHandler.sendMessage(message);
		}
	};
	private Handler myHandler=new Handler(){
		public void handleMessage(android.os.Message msg) {
			Log.d("lhm", "appwidget的长度是"+appWidgetIds.length);
			for (int i = 0; i < appWidgetIds.length; i++) {
				int appWidgetId=appWidgetIds[i];
				//加载对应的布局类
				RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.activity_main);
				//设置时间转化格式
				SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
				views.setTextViewText(R.id.main_time, sdf.format(new Date()));
				appWidgetManager.updateAppWidget(appWidgetId, views);
			}
		};
	};
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值