模仿360安全卫士项目笔记8

来源:互联网 发布:网上商城界面源码jsp 编辑:程序博客网 时间:2024/05/16 15:54


72_得到手机的内存ram信息_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(thisavailRam) + "/"

+ Formatter.formatFileSize(thistotalRam));

 

 

5、解决API不兼容报错

Problems 问题

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

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

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

 

6、了解处理器信息命令

 查看设备命名:adb devices

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

 看目录结构:ls

 进入proccd 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<TaskInfo> getTaskInfos(Context context) {

List<TaskInfo> infos = new ArrayList<TaskInfo>();

ActivityManager am = (ActivityManager) context

.getSystemService(Context.ACTIVITY_SERVICE);

List<RunningAppProcessInfo> 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:定义简单的TextViewItem先演示数据;

 

 

 

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

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

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

例如:

system_process 系统内核进程

Android.process.acore 内核进程

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

 

拷贝一张名字叫:default.png图片到drawble-hdpi目录下提示

invalid symbol 无效的符号

原因是:defaultJava预留的关键字重名了,解决方案是改名一下;

 

 

解决部分程序进程没有名称的问题

 

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

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

taskInfo.setName(packageName);

taskInfo.setIcon(context.getResources().getDrawable(R.drawable.default_icon));

74_CheckBoxListView_30

 

 

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

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

在基础上增加CheckBox

 

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="wrap_content" >

    <ImageView

        android:id="@+id/iv_icon"

        android:layout_width="50dip"

        android:layout_height="50dip"

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

    <TextView

        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" />

 

    <TextView

        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" />

    <CheckBox

        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" />

</RelativeLayout>

 

 

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

 

A:容器

static class ViewHolder{

ImageView iv_icon;

TextView tv_name;

TextView tv_memsize;

CheckBox cb;

}

 

 

 

 

BgetVeiw具体代码

 

 

@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, R.layout.list_task_itemnull);

holder = new ViewHolder();

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

holder.tv_name = (TextView) view.findViewById(R.id.tv_name);

holder.tv_memsize = (TextView) view.findViewById(R.id.tv_memsize);

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

view.setTag(holder);

}

//取出进程信息

TaskInfo info = infos.get(position);

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

holder.tv_name.setText(info.getName());

holder.tv_memsize.setText(Formatter.formatFileSize(TaskManagerActivity.this, info.getMemSize()));

 

return view;

}

 

 

 

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

 

A:定义两个集合

   private List<TaskInfo> userTaskinfos;

private List<TaskInfo> systemTaskinfos;

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

 

private void fillData() {

ll_loading.setVisibility(View.VISIBLE);

new Thread(){

public void run() {

userTaskinfos = new ArrayList<TaskInfo>();

systemTaskinfos = new ArrayList<TaskInfo>();

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 增加字段,并添加getset方法;

//是否被选中

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、在布局文件里面,增加全选、反选、一键清理、设置按钮

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

 

    <TextView

        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" />

 

    <RelativeLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content" >

 

        <TextView

            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" />

 

        <TextView

            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" />

    </RelativeLayout>

 

    <FrameLayout

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:layout_weight="50" >

 

        <ListView

            android:id="@+id/list_task_item"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent" >

        </ListView>

 

        <LinearLayout

            android:id="@+id/ll_loading"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:gravity="center"

            android:orientation="vertical"

            android:visibility="invisible" >

 

            <ProgressBar

                android:layout_width="wrap_content"

                android:layout_height="wrap_content" />

 

            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

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

        </LinearLayout>

 

        <TextView

            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" />

    </FrameLayout>

 

     <LinearLayout

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal" >

 

        <Button

            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" />

 

        <Button

            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" />

 

        <Button

            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" />

 

        <Button

            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" />

    </LinearLayout>

 

 

</LinearLayout>

 

 

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();

}

 

杀进程需要加权限

 <uses-permission 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:看日志:

 java.lang.IllegalStateException: Could not execute method of the activity 不能执行activity这个方法

 

 Caused by: java.util.ConcurrentModificationException 并发更改的异常;

原因是并发导致的,同时修改大小又要显示导致的。

我在遍历的时候,是不可以更改大小的。演示杀最后面的这个,刚好是遍历好了。所有不报错

 

解决方案---把杀死的的单独放到集合里面去,遍历结束后;单独遍历该集合移除对应杀死的进程;

 

B:红色代码表示修改好的

 

public void killAll(View view) {

int total = 0;

long saveMem = 0;

List<TaskInfo> killedTaskInfo = new ArrayList<TaskInfo>();

for (TaskInfo info : userTaskinfos) {

if (info.isChecked()) {

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

am.killBackgroundProcesses(info.getPackageName());

total++;

saveMem += info.getMemSize();

// userTaskinfos.remove(info);

killedTaskInfo.add(info);

}

}

for (TaskInfo info : systemTaskinfos) {

if (info.isChecked()) {

am.killBackgroundProcesses(info.getPackageName());

total++;

saveMem += info.getMemSize();

//systemTaskinfos.remove(info);

killedTaskInfo.add(info);

}

}

for(TaskInfo info : killedTaskInfo){

if(info.getUserTask()){

userTaskinfos.remove(info);

}else{

systemTaskinfos.remove(info);

}

}

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

// fillData();

Toast.makeText(

this,

"杀死了" + total + "个进程,释放了"

+ Formatter.formatFileSize(this, saveMem), 1).show();

adapter.notifyDataSetChanged();

}

 

 

 

 5、解决全部杀死界面不好看的问题,应该做相应屏蔽;

 A:把手机卫士给屏蔽掉,不让杀死自己;

 

 B:在适配器getView()方法最后一行加上代码

 

if(info.getPackageName().equals(getPackageName())){

holder.cb.setVisibility(View.INVISIBLE);

}else{

holder.cb.setVisibility(View.VISIBLE);

}

 

 

C:在点击每一条的事件里也需要屏蔽

 

TaskInfo taskInfo = (TaskInfo) obj;

if(taskInfo.getPackageName().equals(getPackageName())){

return;

}

if (taskInfo.isChecked()) {

cb.setChecked(false);

taskInfo.setChecked(false);

else {

cb.setChecked(true);

taskInfo.setChecked(true);

}

}

 

D:全选事件反选事件地方加上如下代码

在用户程序循环处:

 

    /**

 * 全选

 */

public void selectAll(View view) {

for (TaskInfo info : userTaskinfos) {

if(info.getPackageName().equals(getPackageName())){

continue;

}

info.setChecked(true);

}

for (TaskInfo info : systemTaskinfos) {

info.setChecked(true);

}

adapter.notifyDataSetChanged();

}

 

/**

 * 反选

 */

public void unSelect(View view) {

for (TaskInfo info : userTaskinfos) {

if(info.getPackageName().equals(getPackageName())){

continue;

}

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

}

for (TaskInfo info : systemTaskinfos) {

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

}

adapter.notifyDataSetChanged();

}

 

 

 

 6、更改内存的大小的显示;

killAll()点击事件中最末尾添加代码

runningProcessCount -= total;

availRam +=saveMem;

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

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

+ Formatter.formatFileSize(thisavailRam) + "/"

+ Formatter.formatFileSize(thistotalRam));

 

可用内存+手机卫士占用内存  != 总内存 ; 为什么呢

是因为手机里还运行一些纯C的进程

 

 

 

7、查看进程命令

进入模拟题指令:adb -s emulator-5554 shell

查看进程指令:ps

演示杀掉system_serverkill -9 1022

1022为进程的ID

 

 

 

 

 

76_隐藏和显示系统进程&锁屏清理进程&定时器_34

1、创建新的类TaskManagerSettingActivity,并在清单文件配置;

  A:创建布局文件activity_taskmanager_setting.xml,标题为:“进程设置管理”

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    <TextView

        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" />

    <CheckBox

        android:id="@+id/cb_show_system_process"

        android:text="显示系统进程"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />

</LinearLayout>

 

 

  B:实现点击事件,进入TaskManagerSettingActivity

 

 

 

2、在TaskManagerSettingActivity处理CheckBox的事件,并把状态保持起来。

 

 

cb_show_system_process = (CheckBox) findViewById(R.id.cb_show_system_process);

sp = getSharedPreferences("config"MODE_PRIVATE);

boolean showsystem = sp.getBoolean("showsystem"true);

if(showsystem){

 cb_show_system_process.setText("当前状态:显示系统进程");

 cb_show_system_process.setChecked(true);

}else{

cb_show_system_process.setText("当前状态:不显示系统进程");

cb_show_system_process.setChecked(false);

}

cb_show_system_process.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

if(isChecked){

//选中

cb_show_system_process.setText("当前状态:显示系统进程");

}else{

//没有选中

cb_show_system_process.setText("当前状态:不显示系统进程");

}

Editor editor = sp.edit();

editor.putBoolean("showsystem", isChecked);

editor.commit();

}

});

 

 

3、在TaskManagerActivity里的适配器处理显示和隐藏系统进程

 

在适配器getCount()方法加上如下代码

public int getCount() {

   SharedPreferences sp = getSharedPreferences("config"MODE_PRIVATE);

   boolean showsystem =sp.getBoolean("showsystem", true);

   if(showsystem){

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

   }else{

        return userTaskinfos.size() + 1;

}

}

 

 

4、处理勾选后没有立即显示或隐藏

 

 A:在进入设置页面方法enterSetting()

startActivity(intent);--->修改成

startActivityForResult(intent, 0);

 

 

B:实现activityonActivityResult的方法,里面实现如下代码:

//当更新界面时

//notifyDataSetChanged()->getCount()---->getView()

adapter.notifyDataSetChanged();

 

 

 

 

5、锁屏清理进程

A:简单讲解金山锁屏清理进程的原理和2个小时后清理进程的缺陷

B:在锁屏设置页面加载CheckBox用于勾选就锁屏。

 

    <CheckBox

        android:id="@+id/cb_auto_kill_process"

        android:text="当前状态:锁屏清理进程没有开启"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />

B:初始化代码,监听选中状态

 

cb_auto_kill_process = (CheckBox) findViewById(R.id.cb_auto_kill_process);

final Intent intent = new Intent(this,AutoKillService.class);

boolean runningService = ServiceStatusUtils.isRunningService(this"com.itheima.mobilesafe.service.AutoKillService");

if(runningService){

cb_auto_kill_process.setText("当前状态:开启锁屏后台杀进程");

}else{

cb_auto_kill_process.setText("当前状态:关闭锁屏后台杀进程");

}

cb_auto_kill_process.setChecked(runningService);

cb_auto_kill_process.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

if(isChecked){

cb_auto_kill_process.setText("当前状态:开启锁屏后台杀进程");

startService(intent);

}else{

cb_auto_kill_process.setText("当前状态:关闭锁屏后台杀进程");

stopService(intent);

}

}

});

 

C:锁屏事件,只能在代码注册,系统设计考虑性能;因此创建新的服务AutoKillService

 

 

onCreate()监听锁屏广播

//监听锁屏广播

receiver = new InnerScreenOffReceiver();

IntentFilter filter = new IntentFilter();

filter.addAction(Intent.ACTION_SCREEN_OFF);

registerReceiver(receiver, filter);

 

 

onDestory()取消监听广播

//取消监听广播

unregisterReceiver(receiver);

receiver = null;

 

 

 

D:演示是否能监听到锁屏事件

 

 

E:在服务里杀出后台进程

 // 杀死后台进程的代码

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();

for(RunningAppProcessInfo info : processInfos){

am.killBackgroundProcesses(info.processName);

}

 

 

 

6、使用Timer定期执行某个任务,

 

TaskManagerSettingActivity onCreate()方法里

A:定义成员变量

  private Timer timer;

  private TimerTask task;

 

Timer定时器

B:在onCreate()方法里

    timer = new Timer();

task = new TimerTask() {

@Override

public void run() {

System.out.println("呵呵,我执行了");

}

};

//task 要干的活,when第一次延迟多久 period每次间隔多久

timer.schedule(task, 1000, 5000);

 

 

C:在onDestroy()取消定时器

 

      timer.cancel();

task.cancel();

timer = null;

task = null;

 

77_widget简单入门_20

 

 

1widget 简单入门

 Awidget,最初是由微软的word提出的。

   Widget微件的意思。

后来,国内的一些杀毒厂商也使用,比如瑞星杀毒桌面上的狮子;

 

在装有金山卫士的2.3模拟器长按桌面,高版本的模拟器有单独的窗口小部件;

 

B:查看文档Develop/API Guides /App Widget

 

 

App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates. These views are referred to as Widgets in the user interface, and you can publish one with an App Widget provider. An application component that is able to hold other App Widgets is called an App Widget host. The screenshot below shows the Music App Widget.

文档翻译:

窗口小部件是一个微型的视图,可以嵌入在其他应用程序(如主屏幕)和接收定期更新。这些观点被称为用户界面中的控件,你可以发布一个应用程序部件的供应商。一个应用程序组件,可以容纳其他窗口小部件被称为一个应用程序组件的宿主。下面的截图显示了音乐应用程序组件。

 

2、创建widget必须要做的

 

A:com.itheima.mobilesafe.receiver目录下创建MyWidget并且继承AppWidgetProvider

 

 

B:在功能清单文件注册,参照文档,中间部分直接拷贝过来。

<receiver android:name="com.itheima.mobilesafe.receiver.MyWidget" >

          <intent-filter>

              <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

            </intent-filter>

 

            <meta-data

                android:name="android.appwidget.provider"

                android:resource="@xml/example_appwidget_info/>

     </receiver>

 

 

 

C:在res/xml/创建文件example_appwidget_info.xml拷贝文档内容:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:minWidth="294dp"    android:minHeight="72dp"    android:updatePeriodMillis="86400000"    android:previewImage="@drawable/preview"    android:initialLayout="@layout/example_appwidget"    android:configure="com.example.android.ExampleAppWidgetConfigure" android:resizeMode="horizontal|vertical">

</appwidget-provider>

 

D:讲解具体细节

android:updatePeriodMillis:更新周期毫秒值

86400000这个值是一天24小时更新一次,写1000并没有生效,更新最小时间是半个小时:1800000;

 

android:previewImage:预览图片;

删除就是用默认的android:icon="@drawable/ic_launcher"

 

android:initialLayout:初始的布局文件

创建布局文件app_widget.xml,布局文件有个简单的TextView

    <TextView

        android:id="@+id/textView1"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="大家好我是widget"

        />

 

android:configure:需要对应配置Activity才用到。这个我们不需要。

 

 

android:resizeMode:横竖屏切换,指定大小如何去变化。

 

android:widgetCategory=”home_screen|keyguard”

分别在屏幕主页和锁屏状态也能显示;

 

Android:initialKeyguardLayout=”@layout/example_keyguared”

锁屏状态显示的样式

 

 

 

E:example_appwidget_info.xml文件最终内容

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    android:minWidth="294dp"

    android:minHeight="72dp"

    android:updatePeriodMillis="1800000"

    android:initialLayout="@layout/app_widget"

    >

</appwidget-provider>

 

 

 

F:设置自定义布局文件背景红色,看看widget真实大小

新版本模拟器显示要大一些,老版本模拟器显示要小一些;

 

 

 

 

 

 

 

 

 

78_widget抄布局&反编译_18

1、参照金山手机卫士,反编译得到布局文件;

A:创建新的命令提示符窗口:

 

切换目录命令:cd /d D:\手机卫士\day8\apktool

例如:

C:\Users\Administrator>cd /d D:\手机卫士\day8\apktool

 

B反编译布局文件命令:apktool d 文件名称

 

例如:

D:\手机卫士\day8\apktool>apktool d com.ijinshan.mguard.1324644228599.apk

 

 

 

如何快速找到资源文件

 

根据清单文件去找android.appwidget.action.APPWIDGET_UPDATE

 

找对应的 android:resource

 

 

解决报错

对比市面上软件存在抄袭之风。 百度搜索 网易新闻 腾讯新闻,查看;

 

 

知识拓展:反编译

  

79_widget的更新和生命周期_35

1、解析桌面上自己打开一个应用widget一会就更新了,这不是跟我们之前讲的不一样了吗

 

原因是谷歌默认的实现是这样的。金山卫士是自己实现了更新,代码更新内容;

 

 

2、看打开金山手机卫士Widget空间,看日志

 

3、在服务包里创建服务类UpdateWidgetService  继承Service ,并在功能清单文件配置;

 

A:定义计时器成类的成员变量

   private Timer timer;

private TimerTask task;

 

onCreate()方法里

    timer = new Timer();

task = new TimerTask() {

@Override

public void run() {

}

};

timer.schedule(task, 0, 5000);

 

 

onDestroy方法里取消定时器;

@Override

public void onDestroy() {

super.onDestroy();

timer.cancel();

task.cancel();

timer = null;

task = null;

}

 

 

 

4、在定时器里更新桌面的widget

其实更新另外一个进程的操作;IPC调用,进程间通信;

 

A:使用AppWidgetManager 更新widget,定义成成员变量;

private AppWidgetManager awm;

更新appwidget状态;获取安装appwidget提供者和其他appwidget相关的状态信

 

B在onCreate地方实例化

 

awm = AppWidgetManager.getInstance(this);

 

 

C:定时器里

 

RemoteViews类,继承序列化

A class that describes a view hierarchy that can be displayed in another process. The hierarchy is inflated from a layout resource file, and this class provides some basic operations for modifying the content of the inflated hierarchy

一个类,描述了一个视图的层次结构,可以显示在另一个进程中。分层充气从布局的资源文件,这个类提供了一些基本的操作,用于修改充气层次结构的内容

 

// 更新另外一个进程的操作

RemoteViews views = new RemoteViews(getPackageName(),

R.layout.app_widget);

// 指定更新那个Widget

 ComponentName provider = new ComponentName(

UpdateWidgetService.this, MyWidget.class);

views.setTextViewText(

R.id.process_count,

" 正在运行的软件:"

+ SystemInfoUtils

.getRunningProcessCount(UpdateWidgetService.this));

views.setTextViewText(

R.id.process_memory,

"可用内存:"

+ Formatter

.formatFileSize(

getApplicationContext(),

SystemInfoUtils

.getAvailRam(getApplicationContext())));

awm.updateAppWidget(provider, views);

 

 

 

D:在启动页面SplashActivity里的onCreate()方法启动服务

 

Intent intent = new Intent(this,UpdateWidgetService.class);

startService(intent);

 

这样开启后,如果内存不够了。会被回收。

 

 

E:研究AppWidgetProvider的生命周期。--实现方法并打日志

 

 

F:根据生命周期的特性,

onEnabled()方法里启动服务

Intent intent = new Intent(context,UpdateWidgetService.class);

context.startService(intent);

onDisabled()停止服务

Intent intent = new Intent(context,UpdateWidgetService.class);

context.stopService(intent);

 

onUpdate()也加上启动服务

Intent intent = new Intent(context,UpdateWidgetService.class);

context.startService(intent);

 

5、注意,APK安装在sd卡上,widget在微件列表里无法显示。 android:installLocation="preferExternal"

 

修改过来后,需要卸载,再去安装widget才生效;

 

 

80_延期的意图控制widget的点击事件_15

1、给widget设置点击事件

 

PendingIntent类简介

A description of an Intent and target action to perform with it. Instances of this class are created with getActivitygetBroadcastgetService; the returned object can be handed to other applications so that they can perform the action you described on your behalf at a later time.

 

介绍了一种意图和目标的行动来完成它。这个类的实例与getactivity,getbroadcast,创建getService;返回的对象可以交给其他应用程序,使他们能够履行你的行动描述为您在稍后的时间

 

By giving a PendingIntent to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself (with the same permissions and identity). As such, you should be careful about how you build the PendingIntent: often, for example, the base Intent you supply will have the component name explicitly set to one of your own components, to ensure it is ultimately sent there and nowhere else.

 

通过给一个PendingIntent到另一个应用程序,你赋予它正确的执行该操作,您指定为如果其他应用自己(具有相同的权限和身份)。因此,你应该对如何建立PendingIntent小心:通常,例如,为你供给会有意向的显式设置为一个你自己的组件的组件的名称,以确保它是最终送到那里,没有其他地方。

 

 

//一个延迟的意图,执行的自定义获得

Intent i = new Intent();

i.setAction("com.itheima.mobilesafe.killAll");

//另外一个应用执行延期的意图

PendingIntent pendingIntent  = PendingIntent.getBroadcast(getApplicationContext(), 0,  i, PendingIntent.FLAG_UPDATE_CURRENT);

views.setOnClickPendingIntent(R.id.btn_clear, pendingIntent);

 

 

2、自定义广播KillAllReceiver

在里面实现杀死后台进程代码

@Override

public void onReceive(Context context, Intent intent) {

Log.i(TAG"把所有的后台进程杀死。。。");

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

List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();

for(RunningAppProcessInfo info : infos){

am.killBackgroundProcesses(info.processName);

}

}

 

 

3、功能清单文件配置

<receiver  android:name="com.itheima.mobilesafe.receiver.KillAllReceiver">

      <intent-filter >

            <action android:name="com.itheima.mobilesafe.killAll"/>

       </intent-filter>

 </receiver>

 

 

 

 

知识拓展:抢占入口

Launcher 原生的

腾讯桌面

360桌面

小米桌面

go桌面

awt桌面

 

三星桌面

 

解压软件

输入法

 

路由器 360 百度 小米都在做 ,

浏览器 百度浏览器 360浏览器 UC浏览器 

 

 

 

 

81_应用程序耗电的优化_15

 

考虑小细节

雷军说,小米性能很好,待机两三天没问题;这时被网友吐槽了。

后来回复说:用户装了很多应用+本身系统费电;

 

可以到设置中心-电量-看看谁耗电,谁最多,如果该应用没有使用的话,可以卸载掉。

屏幕是最费电的。

还有,一些应用在后台消耗电量。

 

 

优化耗电

锁屏是把5秒自动更新widget取消掉

 

 

private class InnerScreenReceiver extends BroadcastReceiver {

 

@Override

public void onReceive(Context context, Intent intent) {

if(intent.getAction() ==Intent.ACTION_SCREEN_OFF){

Log.i(TAG"锁屏了...");

if(timer != null&&task !=null){

timer.cancel();

task.cancel();

timer = null;

task = null;

}

}else if(intent.getAction() == Intent.ACTION_SCREEN_ON){

Log.i(TAG"屏了打开了...");

if(timer ==null &&task==null){

startUpdataAppWidget();

}

}

}

}

监听锁屏广播

//监听锁屏事件

offReceiver = new InnerScreenReceiver();

IntentFilter filter = new IntentFilter();

filter.addAction(Intent.ACTION_SCREEN_OFF);

filter.addAction(Intent.ACTION_SCREEN_ON);

registerReceiver(offReceiver, filter);

 

在onDestroy()地方代码修改成

if(timer!=null&&task != null){

timer.cancel();

task.cancel();

timer = null;

task = null;

}

 

 

 

 

 

重构创建定时器代码成startWidgetUpdate()方法

 

 

82_创建桌面快捷图标_35

1、演示金山软件创建一键拨号功能

2、创建一键拨号功能;

3、创建一个工程名叫:创建快捷图标 ,布局里有一个按钮。

4、演示在windows左面上创建快捷图标,并演示更改图片后缀是.ico

 

5、快捷图片的几个要素:

   a、要开启什么;b、名称;c、图标;d、桌面(explorer.exe);

6、演示把window桌面干掉并重新启动的过程;

 

7、把另外一个模拟器arm的桌面干掉;

     A、进入某一个模拟器命令:adb -s emulator-5556 shell

     B、进入system/app/ 演示正常命令删除 rm -r Launcher2.apk 提示是可以读;

     C、重新挂载 mount -o remount  , rw  /system

7、看Launcher的源代码的功能清单文件 ,接收创建快捷图标的意图

8、写代码:

public void click(View view){

Intent intent = new Intent();

//我要创建快捷图标

intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");

//快捷图标的名称

intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "点我打电话");

//快捷图标的图标

intent.putExtra(Intent.EXTRA_SHORTCUT_ICON,   BitmapFactory.decodeResource(getResources(), R.drawable.call));

//一个动作,或者说要干什么

Intent callIntent = new Intent();

callIntent.setAction(Intent.ACTION_CALL);

callIntent.setData(Uri.parse("tel:110"));

intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, callIntent);

sendBroadcast(intent);

}

9、演示报错后拷贝权限com.android.launcher.permission.INSTALL_SHORTCUT

10、演示更换图标for循环8次创建快捷键,

  并讲解为什么在桌面的应用不需要权限;

11、代码移植到启动页面;

//手机卫士开启的意图。

Intent homeIntent = new Intent();

homeIntent.setAction("com.itheima.mobilesafe.home");

homeIntent.addCategory("android.intent.category.DEFAULT");

intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, homeIntent);

sendBroadcast(intent);

 

在布局文件里

<activity  android:name="com.itheima.mobilesafe.HomeActivity" >

           

   <intent-filter>

               

       <action android:name="com.itheima.mobilesafe.home" />

                

      <category android:name="android.intent.category.DEFAULT" />

            

    </intent-filter>

       

</activity>

 

是否安装过快捷方式

booleaninstalledshortcut =  sp.getBoolean("installedshortcut"false);

if(installedshortcut){

return;

}

 

 

保存是否创建过快捷方式

Editor editor = sp.edit();

editor.putBoolean("installedshortcut"true);

editor.commit();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击