简单的widget日历小插件

本文介绍了如何创建一个简单的Android Widget,展示时间、日期和星期信息。通过AppWidgetProvider、AppWidgetProviderInfo、AppWidgetManager和RemoteViews实现,强调了实时更新需求及系统默认更新间隔与自定义定时服务的必要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

widget主要功能就是显示一些信息。我今天编写一个很简单的作为widget,显示时间、日期、星期几等信息。需要显示时间信息,那就需要实时更新,实时更新就需要定时任务,1秒钟更新一次。

这个时间Widget我是参考(Android应用开发揭秘)书里面的一个demo例子做的,效果如下图:


1.AppWidget框架

AppWidget框架主要包括以下类:

  • AppWidgetProvider:继承自BroadcastReceiver,在AppWidget应用update、enable、disable和deleted时接收通知。其中,onUpdate、onReceive是最常用到的方法,他们接收更新通知。
  • AppWidgetProviderInfo:描述Appwidget的大小,更新频率和初始界面等信息,已XML文件存在于应用的res/xml/目录下。
  • AppWidgetManager:负责管理AppWidget,向AppWidgetProvider发送通知。
  • RemoteViews:一个可以再其他应用进程中运行的类,是构造AppWidget的核心。
2.Widget开发流程
  • appWidget配置
代码清单:widget.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/date_layout"
    android:initialLayout="@layout/date_layout"
    android:minHeight="72dp"
    android:minWidth="72dp"
    android:previewImage="@drawable/preview"
    android:updatePeriodMillis="0" >

</appwidget-provider>

•android:initialLayout 指定界面布局的Layout文件,和activity的Layout一样
•android:minWidth 你的widget的最小宽度。根据Layout的单元格计算(72*格子数-2)
•android:minHeigh 你的widget的最小高度。计算方式和minwidth一样。(对这个不了解可以看我Launcher分析文章)
•android:updatePerioMillis 使用系统定时更新服务,单位毫秒。

这里需要说明android:updatePerioMillis的问题,系统为了省电,默认是30分钟更新一次,如果你设置的值比30分钟小,系统也是30分钟才会更新一次。对于我们做时间Widget来说,显然不靠谱。所以只能自己编写一个Alarm定时服务更新。

  • 继承appwidgetProvider的widget
代码清单:TodayDate.java
package com.hutest.android;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.text.format.Time;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.example.widget.R;

public class TodayDate extends AppWidgetProvider {

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		RemoteViews updateView = buildUpdate(context);
		appWidgetManager.updateAppWidget(appWidgetIds, updateView);

		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}

	private String[] months = { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月",
			"九月", "十月", "十一月", "十二月" };
	private String[] dayofWeeks = { "星期一 ", "星期二", "星期三", "星期四", "星期五", "星期六",
			"星期日" };

	private RemoteViews buildUpdate(Context context) {
		RemoteViews updateView = null;
		Time time = new Time();
		time.setToNow();
		//使用Service更新时间
		Intent launchIntent = new Intent(context,UpdateService.class);
		PendingIntent intent = PendingIntent.getService(context, 0,
				launchIntent, 0);
		//使用Alarm定时更新界面数据
		AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
		alarm.setRepeating(AlarmManager.RTC, time.toMillis(true), 1*1000, intent);

		return updateView;
	}

}

使用Alarm定时更新界面数据,刷新时间使用了一个Service,因为要定时刷新服务,还需要一个Alarm定时器服务。
package com.hutest.android;

import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.text.format.Time;
import android.widget.RemoteViews;

import com.example.widget.R;

public class UpdateService extends Service {
	private String[] months = { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月",
			"九月", "十月", "十一月", "十二月" };
	private String[] dayofWeeks = { "星期一 ", "星期二", "星期三", "星期四", "星期五", "星期六",
			"星期日" };

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		UpdateWidget(this);
		return super.onStartCommand(intent, flags, startId);
	}

	private void UpdateWidget(Context context) {
		RemoteViews updateView = null;
		Time time = new Time();
		time.setToNow();
		String month = months[time.month];
		String year = String.valueOf(time.year);
		String monthday = String.valueOf(time.monthDay);
		String weekday = dayofWeeks[time.weekDay - 1];
		String currenttime = String.format("%02d:%02d:%02d", time.hour,
				time.minute, time.second);
		updateView = new RemoteViews(context.getPackageName(),
				R.layout.date_layout);
		updateView.setTextViewText(R.id.textmonth, month);
		updateView.setTextViewText(R.id.textyear, year);
		updateView.setTextViewText(R.id.textday, monthday);
		updateView.setTextViewText(R.id.textweek, weekday);
		updateView.setTextViewText(R.id.texttime, currenttime);
		//点击widget,启动日历
        Intent launchIntent = new Intent();
        launchIntent.setComponent(new ComponentName("com.android.calendar",
                "com.android.calendar.LaunchActivity"));
        launchIntent.setAction(Intent.ACTION_MAIN);
        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        PendingIntent intentAction = PendingIntent.getActivity(context, 0,
                launchIntent, 0);
        updateView.setOnClickPendingIntent(R.id.base, intentAction);
		AppWidgetManager appWidgetManager = AppWidgetManager
				.getInstance(context);
		appWidgetManager.updateAppWidget(new ComponentName(context,
				TodayDate.class), updateView);
	}
}

  • AndroidManifest.xml配置
<manifest package="com.example.widget"
    android:versionCode="1"
    android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver android:label="日历" android:name="com.hutest.android.TodayDate">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget"/>
        </receiver>
        <service android:name="com.hutest.android.UpdateService"></service>
    </application>

</manifest>

有一点需要说明的是RemoteViews
updateView = new RemoteViews(context.getPackageName(),R.layout.date_layout);
从我们的界面配置文件生成一个远程Views更新的对象,这个可以在不同进程中操作别的进程的View。因为Widget是运行在Launcher的进程里面的,而不是一个独立的进程。这也是一种远程访问机制。最后就是加了一个点击桌面Widget启动一个程序的功能,也是使用了PendingIntent的方法。




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值