转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47277691
这篇文章是基于上一篇文章《Android之——获取进程、内存、任务列表》完善的,大家可以先阅读一下上一篇博文《Android之——获取进程、内存、任务列表》,做到心中有数。这篇文章中我主要向大家介绍,如何杀死我们在列表中选中的进程,释放进程所占用的空间。好了,不废话了,咱们直接进入主题吧。
老规矩,还是先唠叨一下这个原理级别的东东吧。
基于上一篇文章,我们在这篇博文中,为ListView中每个条目,增加一个CheckBox,同时,我们为获取到的每一个进程信息增加一个属性,标识是否为选中的状态。为了方便起见,我在这里创建两个上下文菜单,一个是全选功能,当点击这个菜单的时候,列表中除了当前应用的进程以外所有的进程信息,标注为选中状态;一个是“取消选择按钮”,当点击这个按钮的时候,取消所有应用进程的选中状态。点击UI最下方的“一键清理按钮”,则会杀死选中的应用程序进程,释放进程占用的资源。
原理唠叨完了,是不是很简单呢?下面,就让我们一起来实现这些功能吧!
这些功能实现起来并不困难,都是基于上一篇博文《Android之——获取进程、内存、任务列表》完善的,大家如果还没有阅读上一篇博文,请先阅读上一篇博文,这样才能充分理解这篇博文的内容。
这个类中,我们主要是更新了下获取系统所有的进程信息列表的方法getTaskInfos(),上一篇博文中,存在一个问题就是,Android系统中一个应用是由C或者C++编写的时候,它可能没有图标和名称,这时列表中就不会显示这些信息,这样给用户的体验不是很好,所有我在这个方法的异常捕获代码块中,为这样的应用程序设置了默认的图标和名称。
具体代码如下
/** * 获取系统所有的进程信息列表 * @param context * @return */ public static List<TaskInfo> getTaskInfos(Context context){ List<TaskInfo> taskInfos = new ArrayList<TaskInfo>(); PackageManager pm = context.getPackageManager(); ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses(); for(RunningAppProcessInfo info : runningAppProcesses){ TaskInfo taskInfo = new TaskInfo(); //进程名称 String packageName = info.processName; taskInfo.setPackageName(packageName); try { ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0); //图标 Drawable task_icon = applicationInfo.loadIcon(pm); if(task_icon == null){ taskInfo.setTask_icon(context.getResources().getDrawable(R.drawable.ic_launcher)); }else{ taskInfo.setTask_icon(task_icon); } //名称 String task_name = applicationInfo.loadLabel(pm).toString(); taskInfo.setTask_name(task_name); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); taskInfo.setTask_icon(context.getResources().getDrawable(R.drawable.ic_launcher)); taskInfo.setTask_name(packageName); } //进程id int pid = info.pid; taskInfo.setPid(pid); //获取进程占用的内存 android.os.Debug.MemoryInfo[] processMemoryInfo = am.getProcessMemoryInfo(new int[]{pid}); android.os.Debug.MemoryInfo memoryInfo = processMemoryInfo[0]; long totalPrivateDirty = memoryInfo.getTotalPrivateDirty(); //KB taskInfo.setTask_memory(totalPrivateDirty); taskInfos.add(taskInfo); } return taskInfos; }
在这个类中,我新增一个boolean类型的字段,标识当前这个应用程序是否被选中了。
具体代码如下:
//选中状态 private boolean isChecked = false; public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; }
这个文件是ListView显示Item条目信息,我在这个文件中,新增了一个CheckBox按钮,使UI上能够直接看到当前应用程序是否被选中的状态,这样就可以一目了然了。
注意:CheckBox会抢夺屏幕焦点事件和点击事件,我们点击ListView条目时,不能改变CheckBox的选中状态,所有我在这个控件中加入了两个属性:
android:focusable="false" android:clickable="false"这样就解决问题了。
具体代码如下:
<!-- 新增checkBox控件 --> <CheckBox android:id="@+id/cb_task_manager_selected" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:focusable="false" android:clickable="false" android:layout_alignParentRight="true"/>
这个文件主要是显示进程信息的主界面,在这个界面中我们主要的改动是,调整显示进程信息的列表高度,下面放置两个按钮,一个是“一键清理”,一个是“程序设置”,这里我们只对“一键清理”作事件处理,“程序设置”下篇博文将会涉及,敬请期待。
具体代码如下:
<FrameLayout android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" >
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="kill_process" android:text="一键清理"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="程序设置"/> </LinearLayout>
可以说,这个类是我们这个程序的主界面,这个类中,我增加一个一个属性字段ActivityManager,以它来调用杀死后台进程的方法,增加了两个常量,标识上下文菜单的id;在自定义适配器类TaskManagerAdapter中增加了CheckBox信息;同时创建了上下文菜单,一个是“全选”,一个是“取消选择”,分别处理了它们的点击事件;为ListView设置了条目点击事件;最后,重写了“一键清理”按钮的点击事件。
private static final int ALL_SELECTED_ID = 1; private static final int CANCEL_SELECTED_ID = 2; private ActivityManager am;
这个是我们新增的功能,这里,我自定义了一个类来实现OnItemClickListener接口,重写了onItemClick方法,具体的逻辑是:当应用程序原有的状态是选中时,我们将应用程序的状态设置为未选中,同时将CheckBox设置为未选中状态;当应用程序原有的状态是未选中时,我们将应用程序的状态设置为选中,同时将CheckBox设置为选中状态。
具体实现代码如下:
//ListView条目点击事件 private class MyOnItemClickListener implements OnItemClickListener{ @Override public void onItemClick(AdapterView<?> parent, View view, int position,long id) { Log.i("i", "position ====== " +position); CheckBox checkBox = ((ViewHolder) view.getTag()).cb_task_manager_selected; TaskInfo taskInfo = (TaskInfo) mAdapter.getItem(position); //如果是自身应用程序,则直接不执行下面的操作 if(taskInfo.getPackageName().equals(getPackageName())){ return; } if(taskInfo.isChecked()){ taskInfo.setChecked(false); checkBox.setChecked(false); }else{ taskInfo.setChecked(true); checkBox.setChecked(true); } } }之后,我们在onCreate()方法中,为ListView注册条目点击事件。
具体代码如下:
//设置条目点击事件 lv_taskmanage.setOnItemClickListener(new MyOnItemClickListener());
我在这里新增了CheckBox的信息,同时要注意无论怎么选择,当前应用程序是不能被选中的,否则当前应用程序的进程也会被杀死。所以,我在这里做了个判断,如果列进程列表中的某一个进程是当前应用程序的进程,则将CheckBox设置为不可见状态,这样就不能选中当前应用程序的进程了。
具体代码如下:
(1)自定义适配器的getView方法
@Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; ViewHolder holder = null; if(convertView != null){ view = convertView; holder = (ViewHolder) view.getTag(); }else{ view = mInflater.inflate(R.layout.task_manager_item, null); holder = new ViewHolder(); holder.iv_task_manager_icon = (ImageView) view.findViewById(R.id.iv_task_manager_icon); holder.iv_task_manager_name = (TextView) view.findViewById(R.id.tv_task_manager_name); holder.iv_task_manager_memory = (TextView) view.findViewById(R.id.tv_task_manager_memory); <span style="color:#FF0000;">//获取到UI上的CheckBox控件 holder.cb_task_manager_selected = (CheckBox) view.findViewById(R.id.cb_task_manager_selected);</span> view.setTag(holder); } TaskInfo taskInfo = taskInfos.get(position); holder.iv_task_manager_icon.setImageDrawable(taskInfo.getTask_icon()); holder.iv_task_manager_memory.setText("占用的内存:"+TextFormat.formatByte(taskInfo.getTask_memory()*1024)); holder.iv_task_manager_name.setText(taskInfo.getTask_name()); String packageName = taskInfo.getPackageName(); //应用程序是当前运行的程序 if(packageName.equals(getPackageName())){ holder.cb_task_manager_selected.setVisibility(View.GONE); }else{ holder.cb_task_manager_selected.setVisibility(View.VISIBLE); } //获取条目的选中状态 boolean isChecked = taskInfo.isChecked(); if(isChecked){ holder.cb_task_manager_selected.setChecked(true); }else{ holder.cb_task_manager_selected.setChecked(false); } return view; }(2)更新ViewHolder
/** * ViewHolder * @author liuyazhuang * */ static class ViewHolder{ ImageView iv_task_manager_icon; TextView iv_task_manager_name; TextView iv_task_manager_memory; //新增CheckBox属性 CheckBox cb_task_manager_selected; }
这个方法是Android系统自带的一个回调方法,我们只需要重写这个方法即可
具体代码如下:
//创建上下文菜单的回调 @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub menu.add(0, ALL_SELECTED_ID, 0, "全选"); menu.add(0, CANCEL_SELECTED_ID, 0, "取消选择"); return super.onCreateOptionsMenu(menu); }
这个方法,同样是Android系统自带的一个回调方法,我们只需要重写这个方法即可。当我们点击“全选”菜单时,除了当前应用程序以外的进程全部标注为选中状态,当我们点击“取消选择”按钮时,取消所有进程的选中状态,并通知ListView更新列表显示内容。
具体代码如下:
//上下文菜单的点击事件 @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub int id = item.getItemId(); switch (id) { case ALL_SELECTED_ID: //将每个条目设置为选中状态 for(TaskInfo taskInfo : taskInfos){ //不修改自身应用程序的状态 if(!taskInfo.getPackageName().equals(getPackageName())){ taskInfo.setChecked(true); } } //刷新列表 mAdapter.notifyDataSetChanged(); break; case CANCEL_SELECTED_ID: //将每个列表设置为不选中状态 for(TaskInfo taskInfo : taskInfos){ taskInfo.setChecked(false); } //刷新列表 mAdapter.notifyDataSetChanged(); break; default: break; } return super.onOptionsItemSelected(item); }
这个方法很简单,就是遍历所有的进程集合,杀死被选中的进程,释放进程所占用的资源。
具体代码实现如下:
/** * 杀死进程 * @param v */ public void kill_process(View v){ for(TaskInfo taskInfo : taskInfos){ if(taskInfo.isChecked()){ //杀死选中的进程 am.killBackgroundProcesses(taskInfo.getPackageName()); } } }
杀死应用程序是需要权限的,我们需要在AndroidManifest.xml中配置相应的权限。
具体要配置的权限如下:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
1、程序运行界面
2、选中某一个条目中的进程
3、取消选中某一个条目中的进程
4、上下文菜单
5、全选
6、取消全选
7、选择短信应用进行清理
8、清理结果
本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/l1028386804/article/details/47277691