练手小项目(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);
			}
		}
	}
}

点击下载源码

时间: 2024-11-05 17:22:32

练手小项目(5)安全卫士——手机加速的相关文章

练手小项目(2)-生活小助手--周公解梦

第一篇 练手小项目(2)-生活小助手--身份证查询 第二篇 练手小项目(2)-生活小助手--星座运势查询 我在想就是第三个药品查询要不要写出来,因为布局还在讨论用什么展示,因为药品有很多展示,我也不知道用什么展示. 这是一个很纠结的事情 我就先写第四个吧 周公解梦 其中代码有点错误我想用for循环进行判断返回数据有几个 但是总是失败,如果有看本篇贴子,解决了,给我留个言,在这篇帖子我只显示一个结果 布局跟简单的说 一个Edittext 获取数据,然后button进行数据提取发送到服务器 返回的数

练手小项目(2)-生活小助手--星座运势查询

上一篇内容 练手小项目(2)-生活小助手 今天星期一.趁着中午的歇息时间把 第二个写出来 星座运势,近期看看极客学院 用聚合数据做了天气预报的视频教程,不好评价他.看他在后面的代码变更那么大,我就知道,后面肯定做不下去,于是.就改代码了.代码变更那么大,有几个人会去理解,还不如我自己写................ 先看布局 点击去就是一个spinner 用几个textview显示查询内容   布局有点丑,主要是给别人做功能,UI我就不考虑 关于UI  我还是要贴下代码.假设你有想法就把他美化

vue练手小项目--眼镜在线试戴

最近看到了一个眼镜在线试戴小项目使用纯js手写的,本人刚学习vue.js没多久,便试试用vue做做看了,还没完善. 其中包括初始图片加载,使用keywords查找,父子组件之间传递信息,子组件之间传递信息 1. 使用keywords查找 1.1 给每个li添加初始data smallImg: [ { keywords: "椭圆脸", src: "images/model_1.jpg", addClass: false }, { keywords: "圆形脸

java练手小项目!要想java学得好,练手项目不可少!

Java小项目,实现电影院的自动售票机 运行界面如下 2.类的设计 该系统中必须包括两个类,类名及属性方法设置如下. 电影类(Movie) ²  名称(name) ²  上映日期(date) ²  票价(price) 售票机类(TicketSell) ²  方法:查询所有电影信息  查询指定电影票价以及上映日期  购买电影票 3.具体要求及推荐实现步骤 1.创建电影类 2.创建售票机类 3.开发售票机类初始化电影方法,查询方法和买票方法. 1)初始化方法initial():  初始化5个电影对象

练手小项目(5)安全卫士_程序锁bug修复一

程序锁的基本功能,已经实现了,但是你如果输入密码进入 APP以后,看门狗,还是监听你想进入的APP,这时候又会出现一个输入密码的界面. 我先说一下思路. ①思路 1.通过发送自定义广播在服务里面,监控多一个判断如果是临时取消保护的程序就不再启动程序锁 ,这时候,我们要解决的就是什么时候再让他启动监听呢,答案就是 锁屏的时候. 2.通过锁屏将零时保护值设为空就可以继续保护了 但是bug 还是有 那就不停的安返回键 取消 输入密码界面,可以慢慢把界面内容看完,怎么解决呢 解决方案的是: 3. 如果在

练手小项目(1)——智能聊天机器人

我一直坚信着,即使一个最简单的APP,也有他的难点,如果一个复杂的APP你无法做出来,那肯定是你基础不扎实,我身边的人总是问我,安卓为什么学了有忘记了,总是学不好,有些东西记不住,其实这不能怪你,如果别人开发了那么久的东西,你一下子就学会了,你让谷歌怎么活. 篇幅有限,如果读者看不懂的话,可以复习下基础,我尽量将代码简单化了.  先看效果图 如果你是初学安卓,这个APP你可能要半小时 如果你是有经验的开发者,OK,你可能看一遍就能将自己的开发类带入,10分钟不到就搞定. 开发步骤: 1. 先去图

练手小项目:利用pygame库编写飞机大战游戏

pygame库已经很久不更新,毕竟使用python开发游戏的不多.本项目的目的在于训练自己的pthon基本功.了解中小型程序框架以及学习代码重构等.项目出自<Python编程 从入门到实践>中12-14章节的例子.另外写的博客貌似也没人看啊,有点沮丧.不过还是要沉住气,就权当自己的私人技术日记了.或许以后能成为技术大牛呢,傻笑:) giyhub地址: 效果图如下: 程序框架 alien_invasion.py 包含运行游戏的run_game函数 alien.py 外星人类 bullet.py

Spring+Mybatis整合的练手小项目(一)项目部署

声明:教程是网上找的,代码是自己敲的 项目目录大致如下: 1. 首先创建Maven工程,在pom.xml中加入项目所需依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

【辅助程序】练手小程序:记录外网动态IP地址

练手小程序 程序作用:对IP实时记录: 1.定时获取外网IP,存储在本地文件中: 编写思路: 1)收集获取外网的API接口 http://bbs.125.la/thread-13838979-1-1.html 2)定时执行 http://blog.csdn.net/imzoer/article/details/8699083/ 4)记录本地文件 1 # -*- coding: utf-8 -*- 2 # -*- coding: gbk -*- 3 # Date: 2016/4/27 4 # Cr