练手小项目(5)安全卫士——手机加速

不知不觉已经写到了第八篇了,手机卫士作为一个复习基础的项目,我基本也快做完了,如果大家继续看完的话,基本做东西有思路了。

怎么让手机加入加速呢,其实安卓系统是本身不会这么卡的,只因为国内软件太过流氓了,导致内存占用很大,所以手机加速 就说下内存清理

如果看过上一节的软件管理器,应该会很快学懂,因为布局都差不多,还是一个复杂的listview布局

本章涉及到知识点:

1.你猜

2.SP的使用

3.listview的复杂布局

OK ,我还是按照我写教程的思路,先看布局

①.布局的编写


布局就和软件管理器差不多,我就不叙述了。直接看代码吧,源代码在后面供下载,因为在一个测试项目中写的,所以只贴这一部分代码。

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


    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/tv_process_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="运行中的进程:"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/tv_mem_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="剩余/总内存"
            android:textColor="#000000" />
    </RelativeLayout>

    <FrameLayout
        android:layout_weight="9999"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

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

        <ListView
            android:id="@+id/lv_task_manager"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:fastScrollEnabled="true"
            android:overScrollMode="never" >
        </ListView>

        <TextView
            android:id="@+id/tv_status"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#ff888888"
            android:textColor="#ffffff" />
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:onClick="selectAll"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="全选" />

        <Button
            android:onClick="selectOppo"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="反选" />

        <Button
            android:onClick="killAll"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="清理" />

        <Button
            android:onClick="enterSetting"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="设置" />
    </LinearLayout>

</LinearLayout>

② 编写获取进程,内存的工具类

既然是工具类,就单独建立,也是单独抽出来,以后用到这部分就直接调用就行了。

在安卓系统里面,manager 管理器有很多, PackageManager ActivityManager 本章只用到了这两个,我就说下他在安卓系统里面的应用吧。

1 .PackageManager //包管理器 相当于程序管理器。静态的内容。

2.ActivityManager  进程管理器。管理的手机的活动信息。动态的内容。

一 获取正在运行的进程的数量

既然是进程了,就是动态的内容了,我们就用ActivityManager  
	/**
	 * 获取正在运行的进程的数量
	 * @param context 上下文
	 * @return
	 */
	public static int getRunningProcessCount(Context context){
		ActivityManager am =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
		//获得正在运行的进程
		List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();
		return infos.size();
	}

二,获取手机可用剩余内存

内存也是动态内容不是,SO 我们也用ActivityManager  
	/**
	 * 获取手机可用的剩余内存
	 * @param context 上下文
	 * @return
	 */
	public static long getAvailMem(Context context){
		ActivityManager am =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
		//得到内存要存在MemoryInfo中
		MemoryInfo outInfo = new MemoryInfo();
		am.getMemoryInfo(outInfo);
		return outInfo.availMem;
	}

三,获取手机可用总内存

这个时候,因为要考虑到 2.3和4.0的兼容,如果只考虑4.0的话 很简单就是和上面的思路基本一样
//		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
//		MemoryInfo outInfo = new MemoryInfo();
//		am.getMemoryInfo(outInfo);
//		return outInfo.totalMem;

但是呢,这中方法在4.0以下的手机实现不了 得用下面方法
try {
			File file = new File("/proc/meminfo");
			FileInputStream fis = new FileInputStream(file);
			BufferedReader br = new BufferedReader(new InputStreamReader(fis));
			String line = br.readLine();
			//MemTotal:         513000 kB
			StringBuilder sb = new StringBuilder();
			for(char c: line.toCharArray()){
				if(c>='0'&&c<='9'){
					sb.append(c);
				}
			}
			return Long.parseLong(sb.toString())*1024;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}

利用这个类,可以将UI界面最上面的 数据获取到了 。OK,我们继续

③,编写提供手机信息的进程工具类

这个和上一节或许手机软件信息类一样的思路   
县建立实体类,存储东西
package com.example.Darkbutton.TaskmanagerDemo;

import android.graphics.drawable.Drawable;


/**
 * @author xiaoxin007
 * 2014-12-7上午2:26:48
 * TODO  进程信息的业务bean
 */
public class TaskInfo {
	//应用图标
	private Drawable icon;
	//应用名字
	private String name;
	//包名
	private String packname;
	//内存大小
	private long memsize;
	//是否选中
	public boolean isChecked() {
		return checked;
	}
	public void setChecked(boolean checked) {
		this.checked = checked;
	}
	private boolean checked;
	/**
	 * true用户进程 false系统进程
	 */
	private boolean userTask;
	public Drawable getIcon() {
		return icon;
	}
	public void setIcon(Drawable icon) {
		this.icon = icon;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPackname() {
		return packname;
	}
	public void setPackname(String packname) {
		this.packname = packname;
	}
	public long getMemsize() {
		return memsize;
	}
	public void setMemsize(long memsize) {
		this.memsize = memsize;
	}
	public boolean isUserTask() {
		return userTask;
	}
	public void setUserTask(boolean userTask) {
		this.userTask = userTask;
	}
	@Override
	public String toString() {
		return "TaskInfo [name=" + name + ", packname=" + packname
				+ ", memsize=" + memsize + ", userTask=" + userTask + "]";
	}
}

利用获取的到信息 储存起来
package com.example.Darkbutton.TaskmanagerDemo;

import java.util.ArrayList;
import java.util.List;

import com.example.Darkbutton.R;




import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Debug.MemoryInfo;


/**
 * @author xiaoxin007
 * 2014-12-7上午2:25:27
 * TODO 提供手机里面的进程信息
 */
public class TaskInfoProvider {
	public static List<TaskInfo> getTaskInfos(Context context){
		PackageManager pm = context.getPackageManager();
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
		List<TaskInfo> taskInfos = new ArrayList<TaskInfo>();
		for(RunningAppProcessInfo processInfo : processInfos){
			TaskInfo taskInfo = new TaskInfo();
			//得到应用程序的包名。
			String packname = processInfo.processName;
			//设置包名
			taskInfo.setPackname(packname);
			//得到内存大小
			MemoryInfo[] memoryInfos = am.getProcessMemoryInfo(new int[]{processInfo.pid});
			long memsize = memoryInfos[0].getTotalPrivateDirty()*1024l;
			taskInfo.setMemsize(memsize);
			try {//下面步骤和软件管理器那个类是一样的 
				ApplicationInfo applicationInfo = pm.getApplicationInfo(packname, 0);
				//得到程序图标
				Drawable icon = applicationInfo.loadIcon(pm);
				//设置图标
				taskInfo.setIcon(icon);
				//得到名字
				String name = applicationInfo.loadLabel(pm).toString();
				//设置名字
				taskInfo.setName(name);
				//分离出那些事用户进程那些是系统进程
				if((applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0){
					//用户进程
					taskInfo.setUserTask(true);
				}else{
					//系统进程
					taskInfo.setUserTask(false);
				}
			} catch (NameNotFoundException e) {
				e.printStackTrace();
				//系统进程得不到的默认设置其图片
				taskInfo.setIcon(context.getResources().getDrawable(R.drawable.ic_launcher));
				taskInfo.setName(packname);
			}
			taskInfos.add(taskInfo);
		}
		return taskInfos;
	}
}

④利用获取的信息,在ui界面更新

基本也就是初始化组件,初始化数据,给Listview填充数据,主要是adapter 那里逻辑有点复杂 

一 初始化控件


	/**
	 * 初始化控件
	 */
	private void initView() {
		//剩余/总内存
		tv_mem_info = (TextView) findViewById(R.id.tv_mem_info);
		//运行中的进程:
		tv_process_count = (TextView) findViewById(R.id.tv_process_count);
		
		ll_loading = (LinearLayout) findViewById(R.id.ll_loading);
		lv_task_manager = (ListView) findViewById(R.id.lv_task_manager);
		//占位条
		tv_status = (TextView) findViewById(R.id.tv_status);
	}


二,设置标题 

	/**
	 * 设置标题
	 */
	private void setTitle() {
		processCount = SystemInfoUtils.getRunningProcessCount(this);
		tv_process_count.setText("运行中的进程:" + processCount + "个");
		availMem = SystemInfoUtils.getAvailMem(this);
		totalMem = SystemInfoUtils.getTotalMem(this);
		tv_mem_info.setText("剩余/总内存:"
				+ Formatter.formatFileSize(this, availMem) + "/"
				+ Formatter.formatFileSize(this, totalMem));
	}


三,给Listview填充数据

因为这里是一个耗时操作,所以为了用户体验,应该加入一个progressbar 进行显示,填充数据放在线程里面,然后用 runOnUiThread 进行界面更新
	/**
	 * 填充Listview数据
	 */
	private void fillData() {
		ll_loading.setVisibility(View.VISIBLE);
		new Thread() {
			public void run() {
		allTaskInfos = TaskInfoProvider
				.getTaskInfos(getApplicationContext());
		userTaskInfos = new ArrayList<TaskInfo>();
		systemTaskInfos = new ArrayList<TaskInfo>();
		//遍历获得用户进程和系统进程
		for (TaskInfo info : allTaskInfos) {
			if (info.isUserTask()) {
				userTaskInfos.add(info);
			} else {
				systemTaskInfos.add(info);
			}
		}
		// 更新设置界面。
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				ll_loading.setVisibility(View.INVISIBLE);
				if (adapter == null) {
					adapter = new TaskManagerAdapter();
					lv_task_manager.setAdapter(adapter);
				} else {
					adapter.notifyDataSetChanged();
				}
				setTitle();
			}
		});
			};
		}.start();
	}



四,adapter的复杂逻辑

	/**
	 * @author xiaoxin007
	 * 2014-12-7上午3:04:53
	 * TODO 减少控件findbyid的次数
	 */
	static class ViewHolder {
		ImageView iv_icon;
		TextView tv_name;
		TextView tv_memsize;
		CheckBox cb_status;
	}


	private class TaskManagerAdapter extends BaseAdapter {
		//因为在下方有一个设置界面 设置显示系统应用 所以在这里进行设置
		SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
		@Override
		public int getCount() {
			if (sp.getBoolean("showsystem", false)) {
				return userTaskInfos.size() + 1 + systemTaskInfos.size() + 1;
			}else{
				return userTaskInfos.size() + 1 ;
			}
		}

		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			TaskInfo taskInfo;
			if (position == 0) {// 用户进程的标签
				TextView tv = new TextView(getApplicationContext());
				tv.setBackgroundColor(Color.GRAY);
				tv.setTextColor(Color.WHITE);
				tv.setText("用户进程:" + userTaskInfos.size() + "个");
				return tv;
			} else if (position == (userTaskInfos.size() + 1)) {
				TextView tv = new TextView(getApplicationContext());
				tv.setBackgroundColor(Color.GRAY);
				tv.setTextColor(Color.WHITE);
				tv.setText("系统进程:" + systemTaskInfos.size() + "个");
				return tv;
			}else if (position <= userTaskInfos.size()) {
				taskInfo = userTaskInfos.get(position - 1);
			} else {
				taskInfo = systemTaskInfos.get(position - 1
						- userTaskInfos.size() - 1);
			}
			View view;
			ViewHolder holder;
			if (convertView != null && convertView instanceof RelativeLayout) {
				view = convertView;
				holder = (ViewHolder) view.getTag();
			} else {
				view = View.inflate(getApplicationContext(),
						R.layout.list_item_taskinfo, null);
				holder = new ViewHolder();
				holder.iv_icon = (ImageView) view
						.findViewById(R.id.iv_task_icon);
				holder.tv_name = (TextView) view
						.findViewById(R.id.tv_task_name);
				holder.tv_memsize = (TextView) view
						.findViewById(R.id.tv_task_memsize);
				holder.cb_status = (CheckBox) view.findViewById(R.id.cb_status);
				view.setTag(holder);
			}
			holder.iv_icon.setImageDrawable(taskInfo.getIcon());
			holder.tv_name.setText(taskInfo.getName());
			holder.tv_memsize.setText("内存占用:"
					+ Formatter.formatFileSize(getApplicationContext(),
							taskInfo.getMemsize()));
			holder.cb_status.setChecked(taskInfo.isChecked());
			//如果是本机就会隐藏其checkbox
			if (getPackageName().equals(taskInfo.getPackname())) {
				holder.cb_status.setVisibility(View.INVISIBLE);
			} else {
				holder.cb_status.setVisibility(View.VISIBLE);
			}
			return view;
		}
		
	}

五,接下来是下方四个button的点击事件处理

	/**
	 * 选中全部
	 * 
	 * @param view
	 */
	public void selectAll(View view) {
		for (TaskInfo info : allTaskInfos) {
			if (getPackageName().equals(info.getPackname())) {
				continue;
			}
			info.setChecked(true);
		}
		adapter.notifyDataSetChanged();
	}

	/**
	 * 选中相反的
	 * 
	 * @param view
	 */
	public void selectOppo(View view) {
		for (TaskInfo info : allTaskInfos) {
			if (getPackageName().equals(info.getPackname())) {
				continue;
			}
			info.setChecked(!info.isChecked());
		}
		adapter.notifyDataSetChanged();
	}

	/**
	 * 一键清理
	 * 
	 * @param view
	 */
	public void killAll(View view) {
		ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
		int count = 0;
		long savedMem = 0;
		// 记录那些被杀死的条目
		List<TaskInfo> killedTaskinfos = new ArrayList<TaskInfo>();
		for (TaskInfo info : allTaskInfos) {
			if (info.isChecked()) {// 被勾选的,杀死这个进程。
				am.killBackgroundProcesses(info.getPackname());
				if (info.isUserTask()) {
					userTaskInfos.remove(info);
				} else {
					systemTaskInfos.remove(info);
				}
				killedTaskinfos.add(info);
				count++;
				savedMem += info.getMemsize();
			}
		}
		allTaskInfos.removeAll(killedTaskinfos);
		adapter.notifyDataSetChanged();
		Toast.makeText(
				this,
				"杀死了" + count + "个进程,释放了"
						+ Formatter.formatFileSize(this, savedMem) + "的内存", 1)
				.show();
		processCount -= count;
		availMem += savedMem;
		tv_process_count.setText("运行中的进程:" + processCount + "个");
		tv_mem_info.setText("剩余/总内存:"
				+ Formatter.formatFileSize(this, availMem) + "/"
				+ Formatter.formatFileSize(this, totalMem));
	}


	/**
	 * 进入设置
	 * 
	 * @param view
	 */
	public void enterSetting(View view) {
		Intent intent = new Intent(this, TaskSettingActivity.class);
		startActivityForResult(intent, 0);
	}


因为设置了 系统应用再返回,我们就要刷新一下数据所以 ,要加入一个  onActivityResult
@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		adapter.notifyDataSetChanged();
		super.onActivityResult(requestCode, resultCode, data);
	}


⑤ 设置页面的简单业务逻辑

基本就是checkbox的按钮 sp缓存  用服务检测是否存在去检验是否被选中

package com.example.Darkbutton.TaskmanagerDemo;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;

import com.example.Darkbutton.R;
import com.example.Darkbutton.Utils.ServiceUtils;

public class TaskSettingActivity extends Activity {
	private CheckBox cb_show_system;
	private CheckBox cb_auto_clean;
	private SharedPreferences sp;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_task_setting);
		sp = getSharedPreferences("config", MODE_PRIVATE);
		cb_show_system = (CheckBox) findViewById(R.id.cb_show_system);
		cb_auto_clean = (CheckBox) findViewById(R.id.cb_auto_clean);
		cb_show_system.setChecked(sp.getBoolean("showsystem", false));
		cb_show_system
				.setOnCheckedChangeListener(new OnCheckedChangeListener() {
					@Override
					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {
						Editor editor = sp.edit();
						editor.putBoolean("showsystem", isChecked);
						editor.commit();
					}
				});

		cb_auto_clean.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				// 锁屏的广播事件是一个特殊的广播事件,在清单文件配置广播接收者是不会生效的。
				// 只能在代码里面注册里面才会生效。
				Intent intent = new Intent(TaskSettingActivity.this,
						AutoCleanService.class);
				if (isChecked) {
					startService(intent);
				} else {
					stopService(intent);
				}
			}
		});
	};

	@Override
	protected void onStart() {
		boolean running = ServiceUtils.isServiceRunning(this,
				"com.example.Darkbutton.TaskmanagerDemo.AutoCleanService");
		cb_auto_clean.setChecked(running);
		super.onStart();
	}
}

检测服务是否存在工具类
package com.example.Darkbutton.Utils;

import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;

public class ServiceUtils {
/**
 * 检验某个服务是否活着
 * @param context 
 * @param service 服务的包名
 * @return
 */
public static boolean isServiceRunning(Context context ,String service){
	ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
	List<RunningServiceInfo> infos = am.getRunningServices(100);
	for (RunningServiceInfo info : infos) {
		String name = info.service.getClassName();
		if (service.equals(name)) {
			return true;
			
		}
	}
	
	return false;
}
}

接着就是 锁屏清理内存  建立一个服务,在里面手动注册一个广播,因为 安卓规定了 在配置文件中注册是无法生效的 只能代码中手动注册 

package com.example.Darkbutton.TaskmanagerDemo;


import java.util.List;

import android.app.ActivityManager;
import android.app.Service;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

public class AutoCleanService extends Service {
	private ScreenOffReceiver receiver;
	private ActivityManager am;
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	@Override
	public void onCreate() {
		am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
		registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
		super.onCreate();
	}
	@Override
	public void onDestroy() {
		unregisterReceiver(receiver);
		receiver = null;
		super.onDestroy();
	}
	private class ScreenOffReceiver extends BroadcastReceiver{
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.i("ScreenOffReceiver","屏幕锁屏了。。。");
			List<RunningAppProcessInfo>  infos = am.getRunningAppProcesses();
			for(RunningAppProcessInfo info:infos){
				am.killBackgroundProcesses(info.processName);
			}
		}
	}
}

点击下载源码

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。