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

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

《在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程》本文介绍了在Java中使用ModelMapper库简化Shapefile属性转JavaBean的过程,对比... 目录前言一、原始的处理办法1、使用Set方法来转换2、使用构造方法转换二、基于ModelMapper

Java实战之自助进行多张图片合成拼接

《Java实战之自助进行多张图片合成拼接》在当今数字化时代,图像处理技术在各个领域都发挥着至关重要的作用,本文为大家详细介绍了如何使用Java实现多张图片合成拼接,需要的可以了解下... 目录前言一、图片合成需求描述二、图片合成设计与实现1、编程语言2、基础数据准备3、图片合成流程4、图片合成实现三、总结前

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参