最新实战教程,让你了解Android自动化刷量、作弊与防作弊的那些事,案例:刷友盟统计、批量注册苹果帐号
昨天,我们就完成了对应用权限列表的读取,而且还修复了一些小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;
然后重写onActivityResult方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//刷新数据
if(resultCode == 200)
{
initData();
}
}
大家可以看到,当我们的resultCode返回的是200的时候,我们才会刷新数据,那么我们就要在ProcessSettingActivity里面设置一下啦,大家在上面都可以看到的,当我们的CheckBox的状态改变了,我们的resultCode就没设置为200的啦,这样子,我们就可以进行数据的刷新啦。
但是这样还是不行的,我们还要修改一下我们的Adapter才行的
对于显示系统进程,那很简单啦,就是我们原来的样子,但是只显示用户进程,那就要修改一下啦,其实也很简单啦,就是在getCount那里改变一下那个值就可以的啦
@Override
public int getCount()
{
boolean showSystemProcess = sp.getBoolean("showSystemProcess", false);
if(showSystemProcess)
{
// 加上两个标签,一个是系统标签,一个是用户标签
return taskInfos.size() + 2;
}
else
{
return userTaskInfos.size() + 1;
}
}
因为我们之前写的时候,就已经对各种情况判断好的啦,所以就修改一下这里就可以的啦,是不是要显示系统进程,是从SharedPreferences里面读取的
就 这样子,我们的第一个设置就完成的啦,那么接下来,我们不完成我们的第二个设置啦,那就是当用户锁屏的时候,是否要进行进程的清理
其实这个也很简单啦,就是注册一个广播接收者,接收锁屏的广播,当收到广播之后,我们就进行一系列的处理啦
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);
}
}
}
我们把清理进程写在一个util类里面啦,这样方便我们使用
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);
}
}
}
好啦,这样子,我们的广播接收者就写好的啦,现在我们就在AndroidMainfest里面注册它啦
<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