昨天,我们就完成了对应用权限列表的读取,而且还修复了一些小bug,那么今天我们要完成的就是我们的进程设置那一块啦,这里我们做得比较简单,就只是完成两个设置而已
一个就是是否显示系统进程,第二个就是是否在锁屏的时候进行清理一些进程,大家完全可以做得更完善一些的,比如说添加一个进程的白名单啦,这样子,我们一些常用的就用的进程就不会被杀死啊,这类的功能,因为这些都比较容易,所以我就不写了,大家有兴趣的可以完善一下,那么我们现在就来看一下我们今天要做的效果
上面的那一张就是我们的进程设置里面的界面啦,就只有简单的两个设置,我们今天就来完成一下它
对于这些设置信息,我把它保存到我们的SharedPreferences里面的,这样子,下次用户进来,就会先读取原来的信息的
首先,我们就先把界面做一下,这个界面非常的简单,我就不把布局文件粘出来啦,
com.xiaobin.security.ui.ProcessSettingActivity
package com.xiaobin.security.ui; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.view.Window; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import com.xiaobin.security.R; public class ProcessSettingActivity extends Activity { private TextView tv_process_setting_tips; private CheckBox cb_process_setting_state; private TextView tv_process_clean_tips; private CheckBox cb_process_clean_state; private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.process_setting); sp = getSharedPreferences("config", Context.MODE_PRIVATE); boolean showSystemProcess = sp.getBoolean("showSystemProcess", false); tv_process_setting_tips = (TextView) findViewById(R.id.tv_process_setting_tips); cb_process_setting_state = (CheckBox) findViewById(R.id.cb_process_setting_state); if (showSystemProcess) { tv_process_setting_tips.setText("显示系统进程"); cb_process_setting_state.setChecked(true); } else { tv_process_setting_tips.setText("不显示系统进程"); cb_process_setting_state.setChecked(false); } cb_process_setting_state .setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { tv_process_setting_tips.setText("显示系统进程"); Editor editor = sp.edit(); editor.putBoolean("showSystemProcess", true); editor.commit(); // 与前面的ProcessManagerActivity里面的那个resultCode相对应 setResult(200); } else { tv_process_setting_tips.setText("不显示系统进程"); Editor editor = sp.edit(); editor.putBoolean("showSystemProcess", false); editor.commit(); // 与前面的ProcessManagerActivity里面的那个resultCode相对应 setResult(200); } } }); tv_process_clean_tips = (TextView) findViewById(R.id.tv_process_clean_tips); cb_process_clean_state = (CheckBox) findViewById(R.id.cb_process_clean_state); boolean killProcess = sp.getBoolean("killProcess", false); if (killProcess) { tv_process_clean_tips.setText("锁屏清理内存"); cb_process_clean_state.setChecked(true); } else { tv_process_clean_tips.setText("锁屏不清理内存"); cb_process_clean_state.setChecked(false); } cb_process_clean_state.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked) { tv_process_clean_tips.setText("锁屏清理内存"); Editor editor = sp.edit(); editor.putBoolean("killProcess", true); editor.commit(); } else { tv_process_clean_tips.setText("锁屏不清理内存"); Editor editor = sp.edit(); editor.putBoolean("killProcess", false); editor.commit(); } } }); } }
那么,这个activity写好之后,我们就要启动它啦,因为我们第一个设置就是,显不显示系统的进程嘛,那么,如果我选了显示,那我们就要刷新界面的啦,
所以我们就要有一个标记才行,让我们的应用知道什么时候要刷新界面啦,所以我们使用了startActivityForResult这个方法,来启动这个activity
case R.id.bt_process_setting: Intent intent = new Intent(this, ProcessSettingActivity.class); startActivityForResult(intent, 0); break;
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //刷新数据 if(resultCode == 200) { initData(); } }
但是这样还是不行的,我们还要修改一下我们的Adapter才行的
对于显示系统进程,那很简单啦,就是我们原来的样子,但是只显示用户进程,那就要修改一下啦,其实也很简单啦,就是在getCount那里改变一下那个值就可以的啦
@Override public int getCount() { boolean showSystemProcess = sp.getBoolean("showSystemProcess", false); if(showSystemProcess) { // 加上两个标签,一个是系统标签,一个是用户标签 return taskInfos.size() + 2; } else { return userTaskInfos.size() + 1; } }
就 这样子,我们的第一个设置就完成的啦,那么接下来,我们不完成我们的第二个设置啦,那就是当用户锁屏的时候,是否要进行进程的清理
其实这个也很简单啦,就是注册一个广播接收者,接收锁屏的广播,当收到广播之后,我们就进行一系列的处理啦
com.xiaobin.security.receiver.LockScreenReceive
package com.xiaobin.security.receiver; import com.xiaobin.security.utils.ProcessUtil; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; public class LockScreenReceiver extends BroadcastReceiver { private static final String TAG = "LockScreenReceiver"; @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "已经锁屏了"); SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE); boolean killProcess = sp.getBoolean("killProcess", false); if (killProcess) { Log.i(TAG, "开始清理内存"); ProcessUtil.killAllProcess(context); } } }
com.xiaobin.security.utils.ProcessUtil
package com.xiaobin.security.utils; import java.util.List; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.content.Context; public class ProcessUtil { public static void killAllProcess(Context context) { //拿到这个包管理器 ActivityManager activityManager = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); //拿到所有正在运行的进程信息 List<RunningAppProcessInfo> list = activityManager .getRunningAppProcesses(); //进行遍历,然后杀死它们 for (RunningAppProcessInfo runningAppProcessInfo : list) { activityManager .killBackgroundProcesses(runningAppProcessInfo.processName); } } }
<receiver android:name="com.xiaobin.security.receiver.LockScreenReceive"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.SCREEN_OFF"/> </intent-filter> </receiver>
注意,因为我用的是模拟器来测试的,不知道为什么,在我的模拟器里面,通过AndroidMainfest里面注册不上锁屏这个广播接收者的
所以我就在代码里面自己写了,也当温习一下,怎样用代码注册广播接收者
我在自己昨天自己写的MyApplication类里面,重写它的onCreate方法,然后在里面注册广播接收者
@Override public void onCreate() { super.onCreate(); IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF); intentFilter.setPriority(1000); LockScreenReceiver receiver = new LockScreenReceiver(); registerReceiver(receiver, intentFilter); }
好啦,今天就讲到这里的了,今天的内容比较容易,下面我把完整的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.content.Intent; import android.content.SharedPreferences; 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.AdapterView.OnItemLongClickListener; 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 com.xiaobin.security.MyApplication; import com.xiaobin.security.R; import com.xiaobin.security.domain.TaskInfo; import com.xiaobin.security.engine.TaskInfoProvider; import com.xiaobin.security.ui.view.MyToast; 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; private String totalMemory; private String availMemory; private SharedPreferences sp; @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); tv_process_memory.setText(availMemory + "/" + totalMemory); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sp = getSharedPreferences("config", Context.MODE_PRIVATE); activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); // 请求一个自己定义的title,但有一些Android系统是被修改过的, // 所以有可能是无法请求的,如乐Phone或小米的手机,这些系统是被修改过的, // 所以就要判断一下是否请求成功 boolean flags = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.process_manager); if (flags) { // 设置自定义的title getWindow().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() { @Override public 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 ("com.xiaobin.security".equals(taskInfo.getPackageName()) || "system".equals(taskInfo.getPackageName()) || "android.process.media".equals(taskInfo .getPackageName())) { cb_process_state.setVisibility(View.INVISIBLE); return; } if (taskInfo.isCheck()) { taskInfo.setCheck(false); cb_process_state.setChecked(false); } else { taskInfo.setCheck(true); cb_process_state.setChecked(true); } } } }); lv_process_list.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { // adapter里面的getItem返回的值 Object obj = lv_process_list.getItemAtPosition(position); if (obj instanceof TaskInfo) { TaskInfo taskInfo = (TaskInfo) obj; //拿到我们自己定义的application对象 MyApplication myApplication = (MyApplication) getApplication(); //把TaskInfo对象设置进去 myApplication.setTaskInfo(taskInfo); Intent intent = new Intent(ProcessManagerActivity.this, AppDetialActivity.class); startActivity(intent); } return false; } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_process_clear: killTask(); break; case R.id.bt_process_setting: Intent intent = new Intent(this, ProcessSettingActivity.class); startActivityForResult(intent, 0); break; default: break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //刷新数据 if(resultCode == 200) { initData(); } } private void initData() { // 因为这个title是要显示当前进程数目和可用内存的,所以我们每次在这里都调用一下,以更新数据 initTitle(); ll_process_load.setVisibility(View.VISIBLE); new Thread(new Runnable() { @Override public void run() { taskInfoProvider = new TaskInfoProvider( ProcessManagerActivity.this); taskInfos = taskInfoProvider.getAllTask(runningAppProcessInfos); // 计算总内存大小,因为不可以直接获取到总内存的,所以只能计算 // 计算方法就是,全部进程占用的内存,再加上可用的内存,但这样计算是不准确的 long total = 0; for (TaskInfo taskInfo : taskInfos) { total += taskInfo.getMemory(); } // new一个内存的对象 MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); // 拿到现在系统里面的内存信息 activityManager.getMemoryInfo(memoryInfo); // 拿到有效的内存空间 long size = memoryInfo.availMem; // 因为我们拿到的进程占用的内存是以KB为单位的,所以这里要乘以1024,也就是左移10位啦 total = total << 10; // 加上可用的内存,就可以得到总内存啦 total += size; totalMemory = TextFormater.dataSizeFormat(total); 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() { availMemory = getAvailMemory(); tv_process_count.setText("进程数目:" + getRunningAppCount()); tv_process_memory.setText("剩余内存:" + availMemory); } // 一键清理的函数 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(); */ // 显示成我们自己定义的Toast MyToast.showToast(this, R.drawable.notification, "已经杀死了" + total + "个进程!释放了" + TextFormater.getSizeFromKB(memorySize) + "空间"); // 重新加载界面 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); } } } @Override public int getCount() { boolean showSystemProcess = sp.getBoolean("showSystemProcess", false); if(showSystemProcess) { // 加上两个标签,一个是系统标签,一个是用户标签 return taskInfos.size() + 2; } else { return userTaskInfos.size() + 1; } } @Override public 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; } } @Override public long getItemId(int position) { return position; } @Override public 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())); // 设置成不能杀死自己的进程,还有一些系统进程 if ("com.xiaobin.security".equals(taskInfo.getPackageName()) || "system".equals(taskInfo.getPackageName()) || "android.process.media" .equals(taskInfo.getPackageName())) { views.cb_process_state.setVisibility(View.INVISIBLE); } else { views.cb_process_state.setVisibility(View.VISIBLE); } 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
今天源码下载