当前位置: 代码迷 >> Android >> Android之——干掉选中的进程(释放进程占用的空间)
  详细解决方案

Android之——干掉选中的进程(释放进程占用的空间)

热度:7   发布时间:2016-04-27 23:38:55.0
Android之——杀死选中的进程(释放进程占用的空间)
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47277691

这篇文章是基于上一篇文章《Android之——获取进程、内存、任务列表》完善的,大家可以先阅读一下上一篇博文《Android之——获取进程、内存、任务列表》,做到心中有数。这篇文章中我主要向大家介绍,如何杀死我们在列表中选中的进程,释放进程所占用的空间。好了,不废话了,咱们直接进入主题吧。

一、原理

老规矩,还是先唠叨一下这个原理级别的东东吧。

基于上一篇文章,我们在这篇博文中,为ListView中每个条目,增加一个CheckBox,同时,我们为获取到的每一个进程信息增加一个属性,标识是否为选中的状态。为了方便起见,我在这里创建两个上下文菜单,一个是全选功能,当点击这个菜单的时候,列表中除了当前应用的进程以外所有的进程信息,标注为选中状态;一个是“取消选择按钮”,当点击这个按钮的时候,取消所有应用进程的选中状态。点击UI最下方的“一键清理按钮”,则会杀死选中的应用程序进程,释放进程占用的资源。

原理唠叨完了,是不是很简单呢?下面,就让我们一起来实现这些功能吧!

二、实现

这些功能实现起来并不困难,都是基于上一篇博文《Android之——获取进程、内存、任务列表》完善的,大家如果还没有阅读上一篇博文,请先阅读上一篇博文,这样才能充分理解这篇博文的内容。

1、更新TaskUtils类

这个类中,我们主要是更新了下获取系统所有的进程信息列表的方法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;	}

2、更新实体类TaskInfo

在这个类中,我新增一个boolean类型的字段,标识当前这个应用程序是否被选中了。

具体代码如下:

//选中状态	private boolean isChecked = false;		public boolean isChecked() {		return isChecked;	}	public void setChecked(boolean isChecked) {		this.isChecked = isChecked;	}

3、更新task_manager_item.xml

这个文件是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"/>

4、更新task_manager.xml

这个文件主要是显示进程信息的主界面,在这个界面中我们主要的改动是,调整显示进程信息的列表高度,下面放置两个按钮,一个是“一键清理”,一个是“程序设置”,这里我们只对“一键清理”作事件处理,“程序设置”下篇博文将会涉及,敬请期待。

具体代码如下:

1)对FrameLayout的改动

 <FrameLayout        android:layout_width="fill_parent"        android:layout_height="0dip"        android:layout_weight="1" >

2)底部新增按钮

 <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>

5、更新TaskManagerActivity

可以说,这个类是我们这个程序的主界面,这个类中,我增加一个一个属性字段ActivityManager,以它来调用杀死后台进程的方法,增加了两个常量,标识上下文菜单的id;在自定义适配器类TaskManagerAdapter中增加了CheckBox信息;同时创建了上下文菜单,一个是“全选”,一个是“取消选择”,分别处理了它们的点击事件;为ListView设置了条目点击事件;最后,重写了“一键清理”按钮的点击事件。

1)新增字段

	private static final int ALL_SELECTED_ID = 1;	private static final int CANCEL_SELECTED_ID = 2;	private ActivityManager am;

2)新增ListView条目点击事件

这个是我们新增的功能,这里,我自定义了一个类来实现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());

3)更新自定义适配器和ViewHolder

我在这里新增了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;	}

4)新增创建上下文菜单方法

这个方法是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);	}

5)新增自定义菜单点击事件

这个方法,同样是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);	}

6)实现“一键清理”按钮的点击事件

这个方法很简单,就是遍历所有的进程集合,杀死被选中的进程,释放进程所占用的资源。

具体代码实现如下:

	/**	 * 杀死进程	 * @param v	 */	public void kill_process(View v){		for(TaskInfo taskInfo : taskInfos){			if(taskInfo.isChecked()){				//杀死选中的进程				am.killBackgroundProcesses(taskInfo.getPackageName());			}		}	}

6、注册权限

杀死应用程序是需要权限的,我们需要在AndroidManifest.xml中配置相应的权限。

具体要配置的权限如下:

<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>

三、运行效果

1、程序运行界面

2、选中某一个条目中的进程

3、取消选中某一个条目中的进程

4、上下文菜单

5、全选

6、取消全选

7、选择短信应用进行清理

8、清理结果

四、温馨提示

有关本文实例的优化方案,请大家阅读下一篇博文《Android之——杀死用户选中的进程优化》一文。

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案