Android桌面小部件,桌面时钟,天气预报,快速启动等等。是一种常驻程序。
分类:
1.快捷方式:程序快速入口
2.小部件(AppWidget):提醒,通知,控制后台服务,显示数据
3.实时文件夹(已过时)
4.壁纸
桌面小部件特点:
1.不同android设备操作不同
2.不同版本差异(版本分裂)
核心类:
AppWidgetProvider
java.lang.Object
android.content.BroadcastReceiver
android.appwidget.AppWidgetProvider 子类
管理类:
AppWidgetManager 类 为AppWidgetProvider服务的
void updateAppWidget(int appWidgetId, RemoteViews views) 更新小部件视图的
void updateAppWidget(ComponentName provider, RemoteViews views)
写法步骤:
1.定义AppWidgetProvider子类重写方法
2.定义布局文件 小部件的视图 注意用的RemoteViews视图
3.在清单文件中声明AppWidgetProvider子类,关联定义AppWidgetProvider的配置文件
4.定义AppWidgetProvider的配置文件(配置文件位置:工程目录/res/xml/xxx.xml) 用来关联小部件视图,尺寸,图标,更新周期,如下:
android:minHeight="72dp" //尺寸
android:updatePeriodMillis="86400000" //更新周期
android:previewImage="@drawable/creep003" //小部件图标
android:initialLayout="@layout/example_appwidget" //绑定的视图文件
android:configure="com.example.android.ExampleAppWidgetConfigure" //配置的活动界面
>
手动创建配置文件时,界面如下:
如果用导航创建,视图布局和配置文件则会自动创建,如下:
注:RemoteViews 是运行在另一个进程中,而不是应用所在的进程.
RemoteViews views=new RemoteViews(packageName, layoutId)
AppWidget可处理方法:
1.在指定时间执行
2.周期性执行
调用onUpdate() 需要设置属性设置周期时间android:updatePeriodMillis="xxx"
设置周期时间不得小于30分钟(1800000: 30 * 60 * 1000),否则无效。
小部件程序是常驻程序,后台运行占用CPU 频繁占用CPU会影响其他应用,小心资源消耗。
示例1:
由导航自动创建,视图布局比较简单,没贴。
1.AppWidgetProvider子类
public class MyAppWidget extends AppWidgetProvider {
@Override//必须收到update广播才能执行
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
final int N = appWidgetIds.length;//桌面小部件的id数组 指定需要更新的所有id(这里更新所有在桌面的小部件)
for (int i = 0; i < N; i++) {
updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
static void updateAppWidget(Context context,
AppWidgetManager appWidgetManager, int appWidgetId) {
CharSequence widgetText = new Date().toString();//获取系统时间
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.my_app_widget);//远程视图,绑定需要显示的视图
views.setTextViewText(R.id.appwidget_text, widgetText);//修改views容器中textview
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);//更新对应id的小部件对象
}
}
注:可以注册的动作,ACTION_APPWIDGET_UPDATE(必须),ACTION_APPWIDGET_DELETED,ACTION_APPWIDGET_ENABLED,ACTION_APPWIDGET_DISABLED
示例2:
因为如果设置更新周期最小只能30分钟,如果我们要更新很快怎么办,下面演示自定义更新时间。
自定义更新时间可以用发广播的形式配合线程或按钮隔一定时间发广播更新,也可以使用服务进行更新。
1.使用服务
这里实现了图片的轮播功能,布局xml中放了一个ImageView
1.写AppWidgetProvider子类
public class NewAppWidget extends AppWidgetProvider {
public static AppWidgetManager appWidgetManager;
//模拟的图片资源
static int[] ids = { R.drawable.a1, R.drawable.a2, R.drawable.a3,
R.drawable.a4, R.drawable.a5, R.drawable.a6, R.drawable.a7,
R.drawable.a8, R.drawable.a9, R.drawable.a10, R.drawable.a11 };
private static int index;//图片下标
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
super.onUpdate(context, appWidgetManager, appWidgetIds);
NewAppWidget.appWidgetManager = appWidgetManager;//管理器对象
context.startService(new Intent(context, MyService.class));//启动服务
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
// 小部件全部删除时动作
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
context.stopService(new Intent(context, MyService.class));//停止服务
}
/**
* 用于更小部件的服务
* @author qinlang
*
*/
public static class MyService extends Service {
private boolean active = false;//服务运行标识位,优化处理
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
active = true;
new Thread() {
public void run() {
while (active) {
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.new_app_widget);//远程视图绑定布局视图
views.setImageViewResource(R.id.imageView1, ids[index]);//设置对应views中的内容(图片)
ComponentName provider = new ComponentName(
MyService.this, NewAppWidget.class);//提供者
appWidgetManager.updateAppWidget(provider, views);//更新视图
index = (++index) % ids.length;// 取余,循环下标
try {
Thread.sleep(15 * 1000);// 15s刷新一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
active = false;
}
}
}
2.配置文件,文件名new_app_widget_info.xml。
关键的一个地方,就是把更新周期设置为0。
在onUpData()方法中,这样写。设置Intent(Intent这里是你的小部件子类对象),设置一个动作,然后绑定
给PendingIntent发广播(本身AppWidgetProvider类是广播的子类,所有没有另外创建广播类了),再绑定给远程视图上控件的点击事件。
//加载小部件的远程视图,并初始化事件处理,让appWidgetManager绘制到桌面上
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.face);
Intent intent = new Intent(context,MyAppWidgetProvider.class);//intent对象
intent.setAction(ACTION_MY_CLICK);//设置动作
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);//pendingIntent对象是一个广播(可以是活动或服务)
remoteViews.setOnClickPendingIntent(R.id.textRemote, pendingIntent);//设置视图上textRemoto控件的点击事件
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
//响应远程视图的事件处理
if(ACTION_MY_CLICK.equals(intent.getAction())){
//加载小部件的远程视图,让appWidgetManager绘制到桌面上
RemoteViews remoteViews=new RemoteViews(context.getPackageName(),R.layout.face);//远程视图
remoteViews.setTextViewText(R.id.textRemote, new Date().toString());//设置对应内容
ComponentName provider=new ComponentName(context, MyAppWidgetProvider.class);//提供者
AppWidgetManager manager=AppWidgetManager.getInstance(context);//小部件管理器
manager.updateAppWidget(provider, remoteViews);//更新
}
}