Android项目实战--手机卫士29--杀死后台进程

2024-06-09 15:48

本文主要是介绍Android项目实战--手机卫士29--杀死后台进程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



最新实战教程,让你了解Android自动化刷量、作弊与防作弊的那些事,案例:刷友盟统计、批量注册苹果帐号




昨天,我们就已经把那些进程给读取出来,然后再显示到界面上的啦,那么今天,我们就要做一个功能,那就是把进程杀死,达到我们的一键清理的功能

但是在做这个杀死进程的功能之前,我们先来修复一个bug先,大家先看下面的一张图


细心的朋友们可能就会看到的啦,我们在title上面的进程数目显示的是16个,但是在下面的用户进程和系统进程加起来也就只有13个,竟然会少了三个,那是为什么呢

其实,那少了的三个是因为,它是没有界面的,而且是没有对应的ApplicationInfo对象的,所以当我们通过包名来获取到相应的ApplicationInfo对象的时候,就会报错的啦

因为我们try  catch了,所以我们的应用才不会挂掉。

那么我们今天就对这些特殊情况进程处理一下就可以的啦,我们就在catch块里面,把它的包名就设置成应用的名字就行啦,然后再给它加一个默认的图标

			catch (Exception e){e.printStackTrace();//当遇到没有界面的和图标的一些进程时候的处理方式taskInfo.setName(packageName);taskInfo.setSystemProcess(true);taskInfo.setIcon(defaultIcon);}

下面就是完整的,修改后的类

com.xiaobin.security.engine.TaskInfoProvider

package com.xiaobin.security.engine;import java.util.ArrayList;
import java.util.List;import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Debug.MemoryInfo;import com.xiaobin.security.R;
import com.xiaobin.security.domain.TaskInfo;public class TaskInfoProvider
{private PackageManager packageManager;private ActivityManager activityManager;private Drawable defaultIcon;public TaskInfoProvider(Context context){defaultIcon = context.getResources().getDrawable(R.drawable.ic_launcher);packageManager = context.getPackageManager();activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);}public List<TaskInfo> getAllTask(List<RunningAppProcessInfo> runningAppProcessInfos){List<TaskInfo> taskInfos = new ArrayList<TaskInfo>();for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcessInfos){TaskInfo taskInfo = new TaskInfo();int id = runningAppProcessInfo.pid;taskInfo.setId(id);String packageName = runningAppProcessInfo.processName;taskInfo.setPackageName(packageName);try{// ApplicationInfo是AndroidMainfest文件里面整个Application节点的封装ApplicationInfo applicationInfo = packageManager.getPackageInfo(packageName, 0).applicationInfo;// 应用的图标Drawable icon = applicationInfo.loadIcon(packageManager);taskInfo.setIcon(icon);// 应用的名字String name = applicationInfo.loadLabel(packageManager).toString();taskInfo.setName(name);// 设置是否为系统应用taskInfo.setSystemProcess(!filterApp(applicationInfo));}catch (Exception e){e.printStackTrace();//当遇到没有界面的和图标的一些进程时候的处理方式taskInfo.setName(packageName);taskInfo.setSystemProcess(true);taskInfo.setIcon(defaultIcon);}// 可以返回一个内存信息的数组,传进去的id有多少个,就返回多少个对应id的内存信息MemoryInfo[] memoryInfos = activityManager.getProcessMemoryInfo(new int[] { id });// 拿到占用的内存空间int memory = memoryInfos[0].getTotalPrivateDirty();taskInfo.setMemory(memory);taskInfos.add(taskInfo);taskInfo = null;}return taskInfos;}// 判断某一个应用程序是不是用户的应用程序,如果是返回true,否则返回falsepublic boolean filterApp(ApplicationInfo info){// 有些系统应用是可以更新的,如果用户自己下载了一个系统的应用来更新了原来的,// 它就不是系统应用啦,这个就是判断这种情况的if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){return true;}else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0)// 判断是不是系统应用{return true;}return false;}}

好啦,就 这样子,我们的这个bug就修复好的啦,大家可以测试一下,这一次拿到的进程数目就会和title上显示的是一致的啦


那么我们现在就可以来完成我们的杀死后台进程的这个功能啦,这个功能也是非常容易完成的,但在这之前,我们要先来处理一下我们的那个checkbox才行

因为我们是通过点击listview的item来进行选定,然后修改checkbox的状态的,但是现在,我们是无法点击listview里面的item的,因为焦点被checkbox抢过去啦

所以我们要在checkbox的布局文件里面指定两个属性

    <CheckBox android:id="@+id/cb_process_manager_state"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dip"android:focusable="false"android:clickable="false"/>

我们把它的focusable和clickable都设置为false,这样子,它就无法抢夺listview的焦点的啦


那么,我们就可以来完成我们的杀死后台进程的操作啦,首先,我们就先把给我们的listview添加一个点击事件啦

		lv_process_list.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){// adapter里面的getItem返回的值Object obj = lv_process_list.getItemAtPosition(position);if (obj instanceof TaskInfo){cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);TaskInfo taskInfo = (TaskInfo) obj;if (taskInfo.isCheck()){taskInfo.setCheck(false);cb_process_state.setChecked(false);}else{taskInfo.setCheck(true);cb_process_state.setChecked(true);}}}});

首先,我们是会拿到我们所点击的条目所对应的那个对象啦,也就是adapter里面getItem所返回的对象啦,所以我们就判断一下,当它是TaskInfo类型的,那么就进行处理啦

为什么要这样子判断呢,那是因为我们有两个标签的嘛,它们也是会返回的,所以就要进行判断啦,如果点击所对应的对象是TaskInfo的对象,那么就根据它的check状态来设置checkbox的状态啦。


这样子,我们通过点击,就能设置好checkbox的状态啦,那么接下来,我们就要根据checkbox的状态,把那些选定了的进程给杀死

其实这个杀死后台进程也是非常简单的,只需要调用activityManager里面的一个方法就可以的啦,但我们麻烦的就是要刷新界面,所以我们写了一个方法

	// 一键清理的函数private void killTask(){int total = 0;int memorySize = 0;for (TaskInfo taskInfo : systemTaskInfos){if(taskInfo.isCheck()){// 杀死进程activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}for (TaskInfo taskInfo : userTaskInfos){if(taskInfo.isCheck()){activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}Toast.makeText(this,"已经杀死了" + total + "个进程!释放了"+ TextFormater.getSizeFromKB(memorySize) + "空间",Toast.LENGTH_SHORT).show();//重新加载界面adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);}

大家可以看到,杀死进程,就是调用了ActivityManager里面的一个方法killBackgroundProcesses,传递进去的是一个包名

因为我们要刷新界面嘛,而我们的界面是通过我们的list集合里面的数据进行显示的,所以我们就把用户进程和系统进程这两个集合做成了类的变量,然后遍历这两个集合

如果是选定了的,就杀死对应的进程,并移除掉这个对象,并累计杀死的进程数目与释放的内存空间,最后就是重新new一个adapter出来,然后刷新界面


在这里,我要和大家说一下,这个杀死进程,其实并不是真的可以把进程杀死的,其实有一些重要的进程,你一杀死它,它就会马上再开启的,所以并不可能杀死了,后台就没有的啦,大家要清楚认识到这一点


好啦,讲到这里,我们把后台进程干掉的功能也完成的啦,下一次我们就把一些小问题修复一下,如那个title的更新,下面把完成的activity粘出来

com.xiaobin.security.ui.ProcessManagerActivity

package com.xiaobin.security.ui;import java.util.ArrayList;
import java.util.List;import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.xiaobin.security.R;
import com.xiaobin.security.domain.TaskInfo;
import com.xiaobin.security.engine.TaskInfoProvider;
import com.xiaobin.security.utils.TextFormater;public class ProcessManagerActivity extends Activity implements OnClickListener
{private static final int LOAD_FINISH = 1;private TextView tv_process_count;private TextView tv_process_memory;private LinearLayout ll_process_load;private ListView lv_process_list;private Button bt_process_clear;private Button bt_process_setting;private CheckBox cb_process_state;private ActivityManager activityManager;private List<RunningAppProcessInfo> runningAppProcessInfos;private TaskInfoProvider taskInfoProvider;private List<TaskInfo> taskInfos;private TaskInfoAdapter adapter;private List<TaskInfo> userTaskInfos;private List<TaskInfo> systemTaskInfos;@SuppressLint("HandlerLeak")private Handler handler = new Handler(){public void handleMessage(Message msg){switch (msg.what){case LOAD_FINISH:ll_process_load.setVisibility(View.INVISIBLE);adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);// 请求一个自己定义的title,但有一些Android系统是被修改过的,// 所以有可能是无法请求的,如乐Phone或小米的手机,这些系统是被修改过的,// 所以就要判断一下是否请求成功boolean flags = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);setContentView(R.layout.process_manager);if (flags){// 设置自定义的titlegetWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.process_manager_title);}tv_process_count = (TextView) findViewById(R.id.tv_process_count);tv_process_memory = (TextView) findViewById(R.id.tv_process_memory);ll_process_load = (LinearLayout) findViewById(R.id.ll_process_load);lv_process_list = (ListView) findViewById(R.id.lv_process_list);bt_process_clear = (Button) findViewById(R.id.bt_process_clear);bt_process_setting = (Button) findViewById(R.id.bt_process_setting);bt_process_clear.setOnClickListener(this);bt_process_setting.setOnClickListener(this);initData();lv_process_list.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){// adapter里面的getItem返回的值Object obj = lv_process_list.getItemAtPosition(position);if (obj instanceof TaskInfo){cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);TaskInfo taskInfo = (TaskInfo) obj;if (taskInfo.isCheck()){taskInfo.setCheck(false);cb_process_state.setChecked(false);}else{taskInfo.setCheck(true);cb_process_state.setChecked(true);}}}});}@Overridepublic void onClick(View v){switch (v.getId()){case R.id.bt_process_clear:killTask();break;case R.id.bt_process_setting:break;default:break;}}private void initData(){// 因为这个title是要显示当前进程数目和可用内存的,所以我们每次在这里都调用一下,以更新数据initTitle();ll_process_load.setVisibility(View.VISIBLE);new Thread(new Runnable(){@Overridepublic void run(){taskInfoProvider = new TaskInfoProvider(ProcessManagerActivity.this);taskInfos = taskInfoProvider.getAllTask(runningAppProcessInfos);Message msg = new Message();msg.what = LOAD_FINISH;handler.sendMessage(msg);}}).start();}// 拿到当前运行的进程数目private int getRunningAppCount(){runningAppProcessInfos = activityManager.getRunningAppProcesses();return runningAppProcessInfos.size();}// 拿到系统剩余的内存private String getAvailMemory(){// new一个内存的对象MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();// 拿到现在系统里面的内存信息activityManager.getMemoryInfo(memoryInfo);// 拿到有效的内存空间long size = memoryInfo.availMem;return TextFormater.dataSizeFormat(size);}// 设置title的信息private void initTitle(){tv_process_count.setText("进程数目:" + getRunningAppCount());tv_process_memory.setText("剩余内存:" + getAvailMemory());}// 一键清理的函数private void killTask(){int total = 0;int memorySize = 0;for (TaskInfo taskInfo : systemTaskInfos){if (taskInfo.isCheck()){// 杀死进程activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}for (TaskInfo taskInfo : userTaskInfos){if (taskInfo.isCheck()){activityManager.killBackgroundProcesses(taskInfo.getPackageName());total++;memorySize += taskInfo.getMemory();taskInfos.remove(taskInfo);}}Toast.makeText(this,"已经杀死了" + total + "个进程!释放了"+ TextFormater.getSizeFromKB(memorySize) + "空间",Toast.LENGTH_SHORT).show();// 重新加载界面adapter = new TaskInfoAdapter();lv_process_list.setAdapter(adapter);}// ===========================================================================private class TaskInfoAdapter extends BaseAdapter{public TaskInfoAdapter(){// 存放用户的应用进程userTaskInfos = new ArrayList<TaskInfo>();// 存放系统的应用进程systemTaskInfos = new ArrayList<TaskInfo>();for (TaskInfo taskInfo : taskInfos){if (taskInfo.isSystemProcess()){systemTaskInfos.add(taskInfo);}else{userTaskInfos.add(taskInfo);}}}@Overridepublic int getCount(){// 加上两个标签,一个是系统标签,一个是用户标签return taskInfos.size() + 2;}@Overridepublic Object getItem(int position){if (position == 0){return 0; // 显示成用户应用的标签}else if (position <= userTaskInfos.size()){return userTaskInfos.get(position - 1); // 用户应用进程的条目}else if (position == userTaskInfos.size() + 1){return position; // 显示成系统进程的标签}else if (position <= taskInfos.size() + 2){// 系统应用进程的条目return systemTaskInfos.get(position - userTaskInfos.size() - 2);}else{return position;}}@Overridepublic long getItemId(int position){return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){View view;TaskInfoViews views;TaskInfo taskInfo;if (position == 0){// 显示成用户应用的标签return newTextView("用户进程(" + userTaskInfos.size() + ")");}else if (position <= userTaskInfos.size()){// 用户应用进程的条目taskInfo = userTaskInfos.get(position - 1);}else if (position == userTaskInfos.size() + 1){// 显示成系统进程的标签return newTextView("系统进程(" + systemTaskInfos.size() + ")");}else if (position <= taskInfos.size() + 2){// 系统应用进程的条目taskInfo = systemTaskInfos.get(position - userTaskInfos.size()- 2);}else{taskInfo = new TaskInfo();}if (convertView == null || convertView instanceof TextView){view = View.inflate(ProcessManagerActivity.this,R.layout.process_manager_item, null);views = new TaskInfoViews();views.iv_process_icon = (ImageView) view.findViewById(R.id.iv_process_manager_icon);views.tv_process_name = (TextView) view.findViewById(R.id.tv_process_manager_name);views.tv_process_memory = (TextView) view.findViewById(R.id.tv_process_manager_memory);views.cb_process_state = (CheckBox) view.findViewById(R.id.cb_process_manager_state);view.setTag(views);}else{view = convertView;views = (TaskInfoViews) view.getTag();}views.iv_process_icon.setImageDrawable(taskInfo.getIcon());views.tv_process_name.setText(taskInfo.getName());views.tv_process_memory.setText("占用内存:"+ TextFormater.getSizeFromKB(taskInfo.getMemory()));views.cb_process_state.setChecked(taskInfo.isCheck());return view;}private TextView newTextView(String title){TextView tv_title = new TextView(ProcessManagerActivity.this);tv_title.setText(title);return tv_title;}}private class TaskInfoViews{ImageView iv_process_icon;TextView tv_process_name;TextView tv_process_memory;CheckBox cb_process_state;}}

好啦,今天就到这里,有什么不明白的,可以指出来


最后,和大家说一下

为了方便大家的交流,我创建了一个群,这样子大家有什么疑问也可以在群上交流

群号是298440981



今天源码下载



这篇关于Android项目实战--手机卫士29--杀死后台进程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045610

相关文章

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模