文档库 最新最全的文档下载
当前位置:文档库 › 杨光福-手机卫士day8

杨光福-手机卫士day8

杨光福-手机卫士day8
杨光福-手机卫士day8

手机卫士

讲师:杨光福

Day8

72_ 进程管理器的标题栏_41

1、参照金山手机卫士的进程管理

2、创建TaskManagerActvity并在功能清单文件注册。

布局文件基于软件管理界面修改一下。并且修改对应的文字和ID;

运行中的内存:tv_process_count

剩余/总内存:tv_mem_info --memory内存

初始化两个TextView

初始化ActivityManager am;看一看里面要用到的方法;

3.在com.itheima.mobilesafe.utils目录下创建SystemInfoUtils工具类

获取正在运行中进程的总个数:

public static int getRunningProcessCount(Context context) {

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

return am.getRunningAppProcesses().size();

}

获取手机可用的内存信息ram

public static long getAvailRam(Context context){

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

MemoryInfo outInfo = new MemoryInfo();

am.getMemoryInfo(outInfo);

return outInfo.availMem;//byte 为单位的long类型的可用内存大小}

获取手机可用的总内存信息ram

public static long getTotalRam(Context context){

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

MemoryInfo outInfo = new MemoryInfo();

am.getMemoryInfo(outInfo);

return outInfo.totalMem;

}

4、正在运行进程数量、可用ram内存、总内存定义成成员变量

//正在运行的进程数量

private int runningProcessCount ;

//可用内存ram

private long availRam ;

//总的内存ram

private long totalRam;

显示部分代码

tv_process_count.setText("运行中的进程:" + runningProcessCount + "个");

tv_mem_info.setText("剩余/总内存:"

+ Formatter.formatFileSize(this, availRam) + "/"

+ Formatter.formatFileSize(this, totalRam));

5、解决API不兼容报错

Problems 问题

A,讲解报错的原因:在16版本才能用这个API,我们清单文件最低支持9

B,解决方式--直接删除,运行正常显示;

C,人为造错误,删除,运行演示,进入页面崩溃;

6、了解处理器信息命令

查看设备命名:adb devices

进入某一个设备:adb -s emulator-5554 shell

看目录结构:ls

进入proc:cd proc

查看里面文件:ls

Bingder说明:绑定一个服务,返回一个binder,虚拟的设备用它来表示;

cpuinfo:处理器信息;

详细列出文件信息命令:ls -l

查看打开处理器文件信息命令:cat cpuinfo

处理器是奔腾4 1500兆赫兹相当于2004年2005年左右主流的处理器;所以我们模拟器运行起来比默认的要快得多。

切换到arm模拟器:ctrl+c

进入arm模拟器:adb -s emulator-5556 shell

打开cpuinfo处理器文件:cat /proc/cpuinfo

处理器是393.21兆赫兹,比加速的处理器速度慢 5倍左右

7.查看内存信息meminfo 和cpuinfo在同一目录

查看命令:cat meminfo

到电脑打开计算器命令:calc

计算可用总内存信息和金山手机计算出来的比较一下是否一样;

MemFree 可用的内存空间

Cached 缓存内存

8、写具体读去meminfo文件得到内存大小

public static long getTotalRam(Context context) {

try {

File file = new File("/proc/meminfo");

FileInputStream fis = new FileInputStream(file);

BufferedReader bufferedReader = new BufferedReader(

new InputStreamReader(fis));

// MemTotal: 516452 kB * 1024 = byte

String line = bufferedReader.readLine();

StringBuffer buffer = new StringBuffer();

for (char c : line.toCharArray()) {

if (c >= '0' && c <= '9') {

buffer.append(c);

}

}

return (Integer.parseInt(buffer.toString()) * 1024l);

} catch (Exception e) {

e.printStackTrace();

return 0;

}

}

知识拓展,有限山寨手机人为修改配置。就是修改设置页面的信息展示。市面上的软件,得到手机内存大小和信息也是读取这些文件的信息;

例如:鲁大师,安兔兔

73_得到所有进程信息并显示_30

1、在com.ithiema.mobilesafe.engine目录下创建TaskInfoProvider

A:创建方法getTaskInfos(Context context)用于得到系统正在运行的进程信息。

B:创建实例TaskInfo

public class TaskInfo {

private Drawable icon;

private String name;

/**

* byte 为单位

*/

private long memsize;

private boolean userTask;

private String packageName;

}

2、得到系统正在运行的进程信息

public static List getTaskInfos(Context context) {

List infos = new ArrayList();

ActivityManager am = (ActivityManager) context

.getSystemService(Context.ACTIVITY_SERVICE);

List processInfos = am.getRunningAppProcesses();

// 得到包管理器

PackageManager pm = context.getPackageManager();

for (RunningAppProcessInfo info : processInfos) {

TaskInfo taskInfo= new TaskInfo();

// 注意导包android.os.Debug.MemoryInfo

MemoryInfo[] memoryInfo = am

.getProcessMemoryInfo(new int[] { info.pid });

//进程在虚拟机的大小

// memoryInfo[1].dalvikPrivateDirty;

//进程在本地运行的大小-jni调用的C代码运行的大小

// memoryInfo[1].nativePrivateDirty;

// 单位是kb

int memory = memoryInfo[0].getTotalPrivateDirty();

// 内存占用大小

long memorySize = memory * 1024L;

taskInfo.setMemSize(memorySize);

// 包名、进程名

String packageName = info.processName;

taskInfo.setPackageName(packageName);

try {

PackageInfo packInfo = pm.getPackageInfo(packageName, 0);

// 图标

Drawable icon = packInfo.applicationInfo.loadIcon(pm);

taskInfo.setIcon(icon);

// 软件名称

String name = packInfo.applicationInfo.loadLabel(pm).toString();

taskInfo.setName(name);

int falgs = packInfo.applicationInfo.flags;

if ((falgs & ApplicationInfo.FLAG_SYSTEM) == 0) {

// 用户进程

taskInfo.setUserTask(true);

} else {

// 系统进程

taskInfo.setUserTask(false);

}

} catch (NameNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

infos.add(taskInfo);

}

return infos;

}

3、在界面上显示信息

A:初始化ListView,和加载效果布局

list_task_item = (ListView) findViewById(R.id.list_task_item);

ll_loading = (LinearLayout) findViewById(R.id.ll_loading);

B:在onCreate()创建方法fillData()并在里面创建线程,初始化数据。

private void fillData() {

ll_loading.setVisibility(View.VISIBLE);

new Thread(){

public void run() {

infos= TaskInfoProvider.getTaskInfos(TaskManagerActivity.this);

handler.sendEmptyMessage(0);

};

}.start();

}

C:数据加载好后,通知主线程更新界面。

private Handler handler = new Handler(){

public void handleMessage(android.os.Message msg) {

adapter = new TaskInfoAdapter();

ll_loading.setVisibility(View.INVISIBLE);

list_task_item.setAdapter(adapter);

};

};

D:定义简单的TextView做Item先演示数据;

4、解决部分程序进程没有名称的问题--指定默认名称和图片;

原理是:绝大多数应用都是标准的应用,对应APK文件,是有名称和包名的;

但有些系统应用,是内核进程;是比较底层的,不是纯Java写的。主要是C写的。他们是没有名称的;所以获取名称失败;

例如:

system_process 系统内核进程

Android.process.acore 内核进程

Android.process.media 多媒体内核进程

拷贝一张名字叫:default.png图片到drawble-hdpi目录下提示invalid symbol 无效的符号

原因是:default与Java预留的关键字重名了,解决方案是改名一下;解决部分程序进程没有名称的问题

getTaskInfos()方法在异常代码处加上下面两行代码

//系统内核进程没有名称,我们就指定包名为它的名称

taskInfo.setName(packageName);

taskInfo.setIcon(context.getResources().getDrawable(R.drawable.defau lt_icon));

74_带CheckBox的ListView_30

1、自定义每条的item布局文件

基于软件管理的Item修改一下名称和ID

在基础上增加CheckBox

xmlns:android="https://www.wendangku.net/doc/6912082191.html,/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/iv_icon"

android:layout_width="50dip"

android:layout_height="50dip"

android:src="@drawable/app"/>

android:id="@+id/tv_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="5dip"

android:layout_marginTop="3dip"

android:layout_toRightOf="@id/iv_icon"

android:text="软件名称"

android:textColor="#000000"

android:textSize="20sp"/>

android:id="@+id/tv_memsize"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@id/tv_name"

android:layout_marginLeft="5dip"

android:layout_marginTop="1dip"

android:layout_toRightOf="@id/iv_icon"

android:text="内存占用:"

android:textColor="#88000000"

android:textSize="16sp"/>

android:id="@+id/cb"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_centerVertical="true"

android:layout_marginRight="5dip"/>

2、在适配器的个体View里面初始化并完成代码

A:容器

static class ViewHolder{

ImageView iv_icon;

TextView tv_name;

TextView tv_memsize;

CheckBox cb;

}

B:getVeiw具体代码

@Override

public View getView(int position, View convertView, ViewGroup parent) {

View view = null;

ViewHolder holder = null;

if(convertView != null&&convertView instanceof RelativeLayout){ view = convertView;

holder = (ViewHolder) view.getTag();

}else{

view = View.inflate(TaskManagerActivity.this, https://www.wendangku.net/doc/6912082191.html,yout.list_task_item, null);

holder = new ViewHolder();

holder.iv_icon= (ImageView) view.findViewById(R.id.iv_icon);

https://www.wendangku.net/doc/6912082191.html,_name= (TextView) view.findViewById(https://www.wendangku.net/doc/6912082191.html,_name);

https://www.wendangku.net/doc/6912082191.html,_memsize= (TextView) view.findViewById(https://www.wendangku.net/doc/6912082191.html,_memsize);

holder.cb = (CheckBox) view.findViewById(R.id.cb);

view.setTag(holder);

}

//取出进程信息

TaskInfo info = infos.get(position);

holder.iv_icon.setImageDrawable(info.getIcon());

https://www.wendangku.net/doc/6912082191.html,_name.setText(info.getName());

https://www.wendangku.net/doc/6912082191.html,_memsize.setText(Formatter.formatFileSize(TaskManagerActivi ty.this, info.getMemSize()));

return view;

}

3、用户进程和系统进程区分显示

A:定义两个集合

private List userTaskinfos;

private List systemTaskinfos;

B:数据初始化,在fillData()里面加载数据;

private void fillData() {

ll_loading.setVisibility(View.VISIBLE);

new Thread(){

public void run() {

userTaskinfos = new ArrayList();

systemTaskinfos = new ArrayList();

infos=

TaskInfoProvider.getTaskInfos(TaskManagerActivity.this);

for(TaskInfo info : infos){

if(info.getUserTask()){

//用户进程

userTaskinfos.add(info);

}else{

//系统进程

systemTaskinfos.add(info);

}

}

handler.sendEmptyMessage(0);

};

}.start();

}

C:在适配器里getCount()里加上+1 +1

@Override

public int getCount() {

return userTaskinfos.size()+1+systemTaskinfos.size()+1; }

D:在getView里面增加两个TextView

TaskInfo info = null;

if(position ==0){

TextView tv = new TextView(TaskManagerActivity.this);

tv.setBackgroundColor(Color.GRAY);

tv.setTextColor(Color.WHITE);

tv.setTextSize(20);

tv.setText("用户进程("+userTaskinfos.size()+")");

return tv;

}else if(position == (userTaskinfos.size() +1)){

TextView tv = new TextView(TaskManagerActivity.this);

tv.setBackgroundColor(Color.GRAY);

tv.setTextColor(Color.WHITE);

tv.setTextSize(20);

tv.setText("系统进程("+systemTaskinfos.size()+")");

return tv;

}else if(position <= userTaskinfos.size()){

int newposition = position-1;

info = userTaskinfos.get(newposition);

}else{

info = systemTaskinfos.get(position-1-userTaskinfos.size()-1);

}

E:切换用户进程和系统进程数据

if (userTaskinfos != null && systemTaskinfos != null) {

if (firstVisibleItem > userTaskinfos.size()) {

tv_status.setText("系统进程:" + systemTaskinfos.size());

} else {

tv_status.setText("用户进程:" + userTaskinfos.size());

}

}

4、勾选CheckBox拖动,会出现bug,每7条就会自动勾选;

A:讲解原理,为什么会导致这样;

是历史缓存View对象重复利用导致;

B:要想解决该问题,在TaskInfo 增加字段,并添加get和set方法;

//是否被选中

private boolean isChecked;

C:点击每条没有效果--禁用CheckBox点击事件

android:clickable="false"

android:focusable="false"

运行演示,已经有了点击效果

D:设置点击每条事件,点击事件实现如下

点击每条事件代码实现

Object obj = list_task_item.getItemAtPosition(position);

if(obj !=null){

CheckBox cb = (CheckBox) view.findViewById(R.id.cb);

TaskInfo taskInfo = (TaskInfo) obj;

if(taskInfo.isChecked()){

cb.setChecked(false);

taskInfo.setChecked(false);

}else{

cb.setChecked(true);

taskInfo.setChecked(true);

}

}

E:在适配器getItem方法里修改成

public Object getItem(int position) {

TaskInfo info = null;

if(position ==0){

return null;

}else if(position == (userTaskinfos.size() +1)){

return null;

}else if(position <= userTaskinfos.size()){

int newposition = position-1;

info = userTaskinfos.get(newposition);

}else{

info =

systemTaskinfos.get(position-1-userTaskinfos.size()-1);

}

return info;

}

运行演示,还出现重复勾选的问题;

F:在getView()方法里加上校验代码

holder.cb.setChecked(info.isChecked());

运行演示看效果,已经解决重复勾选问题;

75_进程管理器的实现_35

1、在布局文件里面,增加全选、反选、一键清理、设置按钮

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/textView1"

android:layout_width="fill_parent"

android:layout_height="55dip"

android:background="#8866ff00"

android:gravity="center"

android:text="进程管理"

android:textColor="#000000"

android:textSize="22sp"/>

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/tv_process_count"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="5dip"

android:layout_marginTop="5dip"

android:text="运行中进程:"

android:textColor="#000000"

android:textSize="14sp"/>

android:id="@+id/tv_mem_info"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_marginLeft="5dip"

android:layout_marginTop="5dip"

android:text="剩余/总内存:"

android:textColor="#000000"

android:textSize="14sp"/>

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_weight="50" >

android:id="@+id/list_task_item"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

android:id="@+id/ll_loading"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:gravity="center"

android:orientation="vertical"

android:visibility="invisible">

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="给力加载中..."/>

android:id="@+id/tv_status"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:background="#ff888888"

android:text="用户进程(6)"

android:textColor="#ffffff"

android:textSize="20sp"/>

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="0dip"

android:layout_height="wrap_content"

android:layout_weight="1"

android:background="@drawable/button_contacts_selector"

android:onClick="selectAll"

android:text="全选"

android:textSize="14sp"/>

android:layout_width="0dip"

android:layout_height="wrap_content"

android:layout_weight="1"

android:background="@drawable/button_contacts_selector"

android:onClick="unSelect"

android:text="反选"

android:textSize="14sp"/>

android:layout_width="0dip"

android:layout_height="wrap_content"

android:layout_weight="1"

android:background="@drawable/button_contacts_selector"

android:onClick="killAll"

android:text="一键清除"

android:textSize="14sp"/>

android:layout_width="0dip"

android:layout_height="wrap_content"

android:layout_weight="1"

android:background="@drawable/button_contacts_selector"

android:onClick="enterSetting"

android:text="设置"

android:textSize="14sp"/>

2、代码实现全选、反选

/**

*全选

*/

public void selectAll(View view){

for(TaskInfo info : userTaskinfos){

info.setChecked(true);

}

for(TaskInfo info : systemTaskinfos){

info.setChecked(true);

}

adapter.notifyDataSetChanged();

}

/**

*反选

*/

public void unSelect(View view){

for(TaskInfo info : userTaskinfos){

info.setChecked(!info.isChecked());

}

for(TaskInfo info : systemTaskinfos){

info.setChecked(!info.isChecked());

}

adapter.notifyDataSetChanged();

}

运行演示看一下效果。

/**

* 杀死选中的进程

*

* @param view

*/

public void killAll(View view) {

for (TaskInfo info : userTaskinfos) {

if (info.isChecked()) {

// android.os.Process.killProcess(pid);//自杀

am.killBackgroundProcesses(info.getPackageName());

}

}

for (TaskInfo info : systemTaskinfos) {

if (info.isChecked()) {

am.killBackgroundProcesses(info.getPackageName());

}

}

//重新加载数据就可以了

fillData();

}

杀进程需要加权限

android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>

运行演示看效果;

对应DDMS看到进行,演示杀死进程;

系统进程杀死后重启。

知识拓展:杀死进程自杀:android.os.Process.killProcess(pid);

3、杀死进程效果优化&提示杀死了多少个进程和内存信息

查看金山手机卫士、和腾讯管家效果。

public void killAll(View view) {

int total = 0;

long saveMem = 0;

for (TaskInfo info : userTaskinfos) {

if(info.isChecked()) {

// android.os.Process.killProcess(pid);//自杀

am.killBackgroundProcesses(info.getPackageName());

total ++;

saveMem +=info.getMemSize();

userTaskinfos.remove(info);

}

}

for (TaskInfo info : systemTaskinfos) {

if (info.isChecked()) {

am.killBackgroundProcesses(info.getPackageName());

total ++;

saveMem +=info.getMemSize();

systemTaskinfos.remove(info);

}

}

// 重新加载数据就可以了

// fillData();

Toast.makeText(this, "杀死了"+total+"个进程,释放了"+Formatter.formatFileSize(this, saveMem), 1).show();

adapter.notifyDataSetChanged();

}

运行演示:先杀最后一个,再杀中间进程报错。

4、解决错误问题

A:看日志:

https://www.wendangku.net/doc/6912082191.html,ng.IllegalStateException: Could not execute method of the activity 不能执行activity这个方法

相关文档