1.appwidget框架类
- AppWidgetProvider–本质是一个brocastreciever。在appwidget应用enabled,update,delete,disenabled时接受广播。常用的是onRecieve,和onUpdate;
- AppWidgetInfo–是widget的配置信息(包括大小,更新频率等),以xml文件等形式存在于res/xml目录下;
- AppWidgetManager–负责管理 AppWidget ,向 AppwidgetProvider 发送通知;
- RemoteViews–一个可以在其他应用进程中运行的类,向 AppWidgetProvider 发送通知。
2.AppWidget 框架的主要类介绍
1) AppWidgetManger 类
bindAppWidgetId(int appWidgetId, ComponentName provider)
通过给定的ComponentName 绑定appWidgetId
getAppWidgetIds(ComponentName provider)
通过给定的ComponentName 获取AppWidgetId
getAppWidgetInfo(int appWidgetId)
通过AppWidgetId 获取 AppWidget 信息
getInstalledProviders()
返回一个List的信息
getInstance(Context context)
获取 AppWidgetManger 实例使用的上下文对象
updateAppWidget(int[] appWidgetIds, RemoteViews views)
通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件
updateAppWidget(ComponentName provider, RemoteViews views)
通过 ComponentName 对传进来的 RemoeteView 进行修改,并重新刷新AppWidget 组件
updateAppWidget(int appWidgetId, RemoteViews views)
通过appWidgetId 对传进来的 RemoteView 进行修改,并重新刷新AppWidget 组件
2) 继承自 AppWidgetProvider 可实现的方法为如下:
- onDeleted(Context context, int[] appWidgetIds)
- onDisabled(Context context)
- onEnabled(Context context)
- onReceive(Context context, Intent intent Tip:因为 AppWidgetProvider 是继承自BroadcastReceiver 所以可以重写onRecevie 方法,当然必须在后台注册Receiver
- onUpdate(Context context, AppWidgetManager appWidgetManager, int[]
appWidgetIds)
一般来说都是重写onUpdate就够了
3.创建AppWidget步骤
1.继承AppWidgetProvider,实现自己的provider
在manifest.xml中配置自己的provider
<receiver android:name=".reciever.MyProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/myappwidget_info" />
</receiver>
注意,在这里action的name和meta-data的name属性都是固定不变的,分别是android.appwidget.action.APPWIDGET_UPDATE 和 android.appwidget.provider。
android:resource属性是appwidget的配置信息
2.配置myappwidget_info.xml,在res/xml目录下创建新的xml文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/activity_main"
android:minWidth="250dp"
android:minHeight="40dp"
android:previewImage="@mipmap/ic_launcher"
android:updatePeriodMillis="1800000"><!--系统为了省电,默认是30分钟更新一次,如果你设置的值比30分钟小,系统也是30分钟才会更新一次。因为需要频繁更新的Widget,需要自己起一个service进行更新了-->
</appwidget-provider>
在我的例子中实现了自己的serviec用于定时(2秒)更新一次widget
3.remoteviews 的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
tools:context="com.data.www.appwidgetdemo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_up"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_weight="1"
android:text="当前运行程序:25" />
<TextView
android:id="@+id/tv_down"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_weight="1"
android:text="可用内存:2.5G" />
</LinearLayout>
<Button
android:id="@+id/btn_clear"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="一键清理" />
</LinearLayout>
4.实现自己的service用于定时更新
package com.data.www.appwidgetdemo.services;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.widget.RemoteViews;
import com.data.www.appwidgetdemo.R;
import com.data.www.appwidgetdemo.reciever.AutoKillReceiver;
import com.data.www.appwidgetdemo.reciever.MyProvider;
import com.data.www.appwidgetdemo.utils.SystemUtils;
import java.util.Timer;
import java.util.TimerTask;
public class UpdateService extends Service {
private Timer timer;
private TimerTask task;
public static final String ACTION_CLEAR = "self.intent.action.clearprocess";
RemoteViews remoteViews;
public UpdateService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (null!=intent&&ACTION_CLEAR.equals(intent.getAction())){
SystemUtils.clearBackground(new SystemUtils.ClearListener() {
@Override
public void onFinish(String result) {
changeWidgetStatus("finish");
}
@Override
public void onStart() {
changeWidgetStatus("start");
}
@Override
public void onDoingjob() {
changeWidgetStatus("doing");
}
});
}
return super.onStartCommand(intent, flags, startId);
}
private void changeWidgetStatus(String status) {
switch (status) {
case "start":
break;
case "doing":
break;
case "finish":
break;
default:
break;
}
}
@Override
public void onCreate() {
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
int runningTaskCount = SystemUtils.getRunningTaskCount(UpdateService.this);
double avaliMem = SystemUtils.getAvaliMem(UpdateService.this);
ComponentName name = new ComponentName(UpdateService.this, MyProvider.class);
remoteViews = new RemoteViews(getPackageName(), R.layout.activity_main);
//更新widget中的组件内容
remoteViews.setTextViewText(R.id.tv_up,"正在运行的程序数:"+runningTaskCount);
remoteViews.setTextViewText(R.id.tv_down,"可用内存:"+avaliMem+" M");
//点击按钮事件处理
Intent intent = new Intent(UpdateService.this, AutoKillReceiver.class);
intent.setAction("self.intent.brocast.autokillprocess");
PendingIntent pendingIntent = PendingIntent.getBroadcast(UpdateService.this,0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.btn_clear,pendingIntent);
//注意,一定要使用Appwidgetmanager处理widget
AppWidgetManager awm = AppWidgetManager.getInstance(getApplicationContext());
awm.updateAppWidget(name,remoteViews);
}
};
timer.schedule(task,3000,2000);
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
task.cancel();
timer=null;
task = null;
}
}
由于只是模拟,所以并没有真正实现清空运行程序的功能。后续会把该功能完善,然后加入点击widget按钮的动画效果(类似360点击正在清理的转圈功能)。
源码:https://github.com/VenQi/AppWidgetDemo