最新實戰教程,讓你瞭解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