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、清理结果

四、温馨提示

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

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

时间: 2024-10-08 04:34:17

Android之——杀死选中的进程(释放进程占用的空间)的相关文章

Android之——杀死用户选中的进程优化

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47281055 在上一篇博文<Android之--杀死用户选中的进程(释放进程占用的空间)>一文中,向大家介绍了如何杀死用户选中的进程,但是,遗留了一个问题,那就是杀死进程后,ListVIew列表没有立即刷新,这篇文章我们就来解决这个问题,优化一下ListView的显示,提升用户体验.我们这篇博文同样是基于上一篇博文来进行优化的,请大家先阅读上一篇博文<Android之--

Android学习笔记二十六.跨进程调用Service(AIDL Service)

跨进程调用Service(AIDL Service) 一.AIDL Service 1.什么是AIDL Service? AIDL,即Android Interface Definition Language.是Android用于定义远程接口,AIDL接口定义语言的语法比较简单,这种接口定义语言并不是真正的编程语言,它只是定义两个进程之间的通信接口.AIDL的语法与Java接口很相似,但存在如下几点差异: (1)AIDL定义接口的源代码必须以.aidl结尾; (2)AIDL接口中用到数据类型,除

linux命令(10)使用kill杀死含有指定关键字的进程

命令:ps -ef|grep keyword|grep -v grep|cut -c 9-15|xargs kill -9 批量杀死包含关键字“keyword”的进程. "ps -ef" ——查看所有进程 "grep keyword" ——列出所有含有关键字"./amplxe-gui"的进程 "grep -v grep" ——在列出的进程中去除含有关键字"grep"的进程(因为我们在前一步生成的grep进程

Linux批量杀死包含某个关键字的进程

ps -ef|grep ./amplxe-gui|grep -v grep|cut -c 9-15|xargs kill -9 批量杀死包含关键字"./amplxe"的进程. "ps -ef" --查看所有进程 "grep ./amplxe-gui" --列出所有含有关键字"./amplxe-gui"的进程 "grep -v grep" --在列出的进程中去除含有关键字"grep"的进程

linux 中批量杀死包含某个关键字的进程

去公司面试的时候关于Linux命令一般会问这个问题: 批量杀死包含php的所有进程...... 一开始我是不会的,只知道ps找出来进程.后来知道了可以用grep过滤出包含Php的进程,后来又知道了用kill -9 可以杀死,后来又知道了用xargs 可以进行参数代换,所以记录一下. ps -aux | grep "php" | grep -v grep | cut -c 9-15 | xargs kill -9 分成5段,利用管道命令传递. 第一段是列出所有的进程: 第二段是过滤出包含

找到并杀死一个软件开启的进程

后台运行 找到并杀死一个软件开启的进程 1.ps 命令用于查看当前正在运行的进程.grep 是搜索例如: ps -ef | grep uwsgi表示查看所有进程里 CMD 是 uwsgi 的进程信息2.ps -aux | grep uwsgi-aux 显示所有状态ps3. kill 命令用于终止进程例如: kill -9 [PID]-9 表示强迫进程立即停止通常用 ps 查看进程 PID ,用 kill 命令终止进程 创建软连接 ln -s 文件目录 /usr/bin 可用的cmd命令 查看一个

Linux - 进程 (二) 进程创建

详细见:https://github.com/ZhangzheBJUT/linux 一 进程概述 一个进程都由另一个称之为父进程的进程启动,被父进程启动的进程叫做子进程.Linux系统启动时候,它将运行一个名为init的进程,该进程是系统运行的第一个进程,它的进程号为1,它负责管理其它进程,可以把它看做是操作系统进程管理器,它是其它所有进程的祖先进程.系统中的进程要么是由init进程启动,要么是由init进程启动的其他进程启动. 使用ps命令输出中的PPID栏给出的是父进程的进程ID,它是启动这

linux进程管理——进程管理相关命令

linux系统上与进程有关的命令: 查看类命令: ps,pstree,pidof,pgrep\pkill,top,htop,glances,dstat,vmstat,pmap 管理类命令: bg,fg,jobs,kill,killall,nohup,nice,renice pstree命令: pstree - display a tree of processes 显示进程之间的关系,用树状图表示 ps命令: ps - report a snapshot of the current proce

Linux中的进程及进程控制

一.整体大纲 二.基础知识 1. 进程相关概念 1)程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁....)     进程,是一个抽象的概念,与操作系统原理联系紧密.进程是活跃(运行起来的)的程序,占用系统资源.在内存中执行.(程序运行起来,产生一个进程).     程序 → 剧本(纸) 进程 → 戏(舞台.演员.灯光.道具...),同一个剧本可以在多个舞台同时上演.同样,同一个程序也可以加载为不同的进程(彼此之间互不影响)     如:同