桌面小控件(Widget)--之清理进程

首先,简单的说一下什么是Widget,Widget是在Android系统界面中添加的小部件。那么在android中有一个系统内置服务来专门管理widget,该服务为AppWidgetManager。


建立widget的步骤如下:
1.建立一个工程,然后写一个类继承AppWidgetProvider并重写onEnabled(), onUpdate(), onDisabled()方法
  class TimeWidgetProvider extends AppWigetProvider
  {
  } 
2. AppWigetProvider是一个广播接者。在配置文件中进行配置:
<receiver android:name=".receiver.MyWidget" >                 
      <intent-filter>                         
          <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />    
      </intent-filter>                     
      <meta-data android:name="android.appwidget.provider“
        android:resource="@xml/appwidget_info" />
 </receiver> 
3.在res文件夹下建一个xml文件夹,放置一个appwidget_info.xml该文件为widget的界面
在桌上第一个添加该widget时系统会发出一个广播,该广播会被我们定义的TimeWidgetProvider所接收,并执行onEnabled()方法,该widget添加后会发出一个广播,该广播的类型为:
android.appwidget.action.APPWIDGET_UPDATE 会执行onUpdate()方法,当桌面上同类型的Widget的最后一个被删除时会执行onDisabled()方法.
在onUpate()方法中可以更改widget界面上的内容.

 

效果图如下:

wKioL1LFMeOC4cTwAABf1obg3pU154.jpg

 

当我们点击一键清理的时候,就会把手机的一些正在运行的进程结束掉,当然用户系统在没有获得root权限之前是不可以结束掉的。

 

步骤一

写一个类,继承AppWidgetProvider

package cn.cbd.clean;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
public class CleanWidget extends AppWidgetProvider
{
private Intent service;
@Override
public void onDeleted(Context context, int[] appWidgetIds)
{
super.onDeleted(context, appWidgetIds);
}
@Override
public void onDisabled(Context context)
{
//停止服务
service = new Intent(context, MyService.class);
context.stopService(service);
super.onDisabled(context);
}
@Override
public void onEnabled(Context context)
{
//开启服务
service = new Intent(context, MyService.class);
context.startService(service);
super.onEnabled(context);
}
@Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
{
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}

         AppWidgetProvider也是一个广播接收者,所以我们要在清单文件中对CleanWidget进行配置

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<receiver android:name=".CleanWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<!-- meta-data  携带数据 传递数据用的 -->
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>

 

在类CleanWidget中我们可以看到,我们在ouEnabled()方法中开启一个服务,在onDisabled()中关闭这个服务,当我们把小控件拖到桌面上的时候,就会先执行onReceive 然后紧接着执行onEnable()方法,当我们把桌面上相同的最后一个控件删除,就会执行onDisabled()方法。

那我们在服务中做哪些事情呢?

package cn.cbd.clean;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.text.format.Formatter;
import android.widget.RemoteViews;
public class MyService extends Service
{
private List<String> packageNames;
private static final String BUTTON_KILLPROCESS = "cn.cbd.KILLPROCESS";
private Timer timer;
@Override
public void onCreate()
{
//新建一个计时器,来不断的×××正在运行程序的个数是否发生改变
timer = new Timer();
timer.schedule(new TimerTask()
{
public void run()
{
//新建一个String类型集合,来存放正在运行程序的包名(我们结束进程是需要通过应用程序的包名来结束的)。
packageNames = new ArrayList<String>();
//获取AppWidgetManager控件管理者对象
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(getApplicationContext());
ActivityManager am = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();
for (RunningAppProcessInfo info : infos)
{
packageNames.add(info.processName);
}
//对于本应用来说,桌面的控件属于远程View了,所以我们需要一个RemoteViews对象,来管理我们自定义View
RemoteViews views = new RemoteViews(getApplicationContext()
.getPackageName(), R.layout.memorycleanning);
//设置控件上的文字内容
views.setTextViewText(R.id.tv_runningAppNums, "正在运行程序有"
+ (packageNames.size() + "个"));
views.setTextViewText(
R.id.tv_availableMemory,
"剩余内存"
+ Formatter.formatFileSize(
getApplicationContext(),
MemoryUtil
.getAvailableMem(getApplicationContext())));
//当我们点击一键清理按钮时发送一个自定义广播,类型为cn.cbd.KILLPROCESS 配置文件中也要进行相应的配置
Intent intent = new Intent();
intent.setAction(BUTTON_KILLPROCESS);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
//为小控件上的按钮设置点击事件
views.setOnClickPendingIntent(R.id.btn_clean, pendingIntent);
ComponentName componentName = new ComponentName(
getApplicationContext(), CleanWidget.class);
//更新AppAidget 也就是更新桌面控件中的内容
appWidgetManager.updateAppWidget(componentName, views);
}
}, 0, 10);
super.onCreate();
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onDestroy()
{
super.onDestroy();
}
}

自定义广播在配置文件中的配置情况

<!-- 广播接收者 自定义了一种广播 -->
<receiver android:name=".KillProcessBroadcaseReceiver" >
<intent-filter>
<action android:name="cn.cbd.KILLPROCESS" />
</intent-filter>
</receiver>

 

此时,显然我们要写一个广播接收者,来接收我们这种类型的广播

package cn.cbd.clean;
import java.util.ArrayList;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.text.format.Formatter;
import android.widget.RemoteViews;
public class KillProcessBroadcaseReceiver extends BroadcastReceiver
{
private List<String> packageNames;
@Override
public void onReceive(Context context, Intent intent)
{
packageNames = new ArrayList<String>();
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.memorycleanning);
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();
for (RunningAppProcessInfo info : infos)
{
packageNames.add(info.processName);
}
String action = intent.getAction();
if (action.equals("cn.cbd.KILLPROCESS"))
{
for (String packageName : packageNames)
{
am.killBackgroundProcesses(packageName);
}
ComponentName componentName = new ComponentName(context,
CleanWidget.class);
views.setTextViewText(R.id.tv_runningAppNums, "正在运行程序有"
+ packageNames.size() + "个");
views.setTextViewText(
R.id.tv_availableMemory,
"剩余内存"
+ Formatter.formatFileSize(context,
MemoryUtil.getAvailableMem(context)));
appWidgetManager.updateAppWidget(componentName, views);
}
}
}

在这个广播中,我们会用到一个工具类,就是获取手机RAM剩余内存大小的。这个类是我们自定义的工具类。

package cn.cbd.clean;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
/**
* 工具类,用来获取手机剩余内存大小
* @author Administrator
*
*/
public class MemoryUtil
{
//Formatter.formatFileSize(this,availaleMemory) 格式化
public static long getAvailableMem(Context context)
{
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
MemoryInfo outInfo= new MemoryInfo();
am.getMemoryInfo(outInfo);
return outInfo.availMem;
}
}

到此呢,我们这个清理手机进程的小控件已经完成。现在呢,我整理一下这个小项目的思路:

1.得到一个Widget对象(继承AppWidgetProvider)

2.开启一个服务,来更新控件上数据的变化

3.在服务中定义一个广播,当我们点击“一键清理”按钮时,就会发送一个广播。这时候呢,需要我们写一个广播接收者,来接收我们定义的这种类型的广播。

4.在广播中,我们做杀掉进程的操作。