您的位置:首页 > 移动开发 > Android开发

android 项目之软件锁

2013-12-02 13:55 106 查看
前言

最近做了个小东西--软件锁。过程还算是顺利,一边扒看别人的源代码,一边补充遇到的技术知识点。现在记录下来分享给大家也是备自己以后温故。

需求

手机有些应用只能自己使用而不方便其他人使用,例如短信。有时不想让孩子拿到手机后就奔命的玩游戏。应对这些需求,软件锁也就腾空出世了。

原理

说起原理其实一句话就可以概括了。启动被加锁的的应用时弹出一个输入密码的界面。这。。。过于简单了吧!呵呵。大家都知道处在前台栈顶的Activity 才能显示在用户面前,与用户交互。我们不停得检测栈顶的 Activity 所属的 App 是不是属于被加锁的 App。如果是就启动输入密码的界面。把原来的 App 界面覆盖了。内部程序实际是把启动的输入密码界面的 Activity 压入了栈。



图 1

功能

软件锁要做的事就是设置解锁密码、给应用加锁、输入密码给应用解锁,还有给处在加锁状态的App 解锁。操作流程大致如下:打开软件锁,第一次使用软件锁时需要设置密码。密码输入完成后进入已加锁应用界面,该界面显示所有已被加锁的应用。在此界面点击应用自动解锁。点击“添加要加锁的软件” 按钮则进入未加锁应用界面,该界面显示未被加锁的应用。在此界面点击应用自动加锁。

界面

涉及的知识点

自定义控件、SQLite数据库操作、ListView优化显示、BroadcastReceiver组件、获取软件信息、Activity启动模式及Flag作用、Handler、动画、AsyncTask和Service组件等等。

数据库设计

数据库只包含一张表,表名为 “t_software_lock” ,用来存储手机中安装的App信息。字段包含:_id(序列号), name(应用名称), packageName(应用包名), appIcon(应用图标), isLocked(是否被加锁,默认false)。

建表语句:

create table if not exists t_software_lock( _id integer primary key autoincrement, name text,packageManager text, appIcon blog, isLocked text default false)


详细设计

软件锁包含一个服务和三个 Activity 组件。在第一次使用时,会启动一个服务,该服务主要功能是周期性检查栈顶并判断及启动输入密码界面。三个Activity分别为输入密码界面、显示加锁App界面和显示未加锁App界面。软件锁启动时会首先显示输入密码界面。我们就先来看看输入密码界面的设计。

输入密码界面( SetPasswordActivity.java ):

在启动时会查询数据库,如果没有数据则搜集手机上已安装的APP信息,并将信息插入到数据库中。也会获取软件锁密码,如果软件锁密码为空即可认为此次使用是软件锁第一次使用,就要启动软件锁服务。下面就是流程图:



public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.set_password_activity);
initView();

isTempLauncher = getIntent().getBooleanExtra("isTempLauncher", false);
password = getPassword();
if(password != null && !password.equals("")) {
//布局文件中功能按钮文字是“下一步”,在此不是第一次使用软件锁就不需要设置密码
//所以把功能按钮的文字更新为“确定”
Util.updataButtonText(nextStepImageButton, getResources().getString(R.string.ok));
flag = 1;
} else {
//启动软件锁服务
Intent intent = new Intent();
intent.setClass(SetPasswordActivity.this, LockSoftService.class);
startService(intent);
}
setOnClick();
new InitDB().start();//开启线程用来检测数据库是否为空及插入数据
}


软件锁打开时需要正确输入密码才可以使用,如果是第一次使用,就需要设置密码,此时界面的按钮字体为 “下一步” 。在输入密码点击下一步按钮之后,按钮字体更换为“确定”。等待用户再次输入密码,输入之后点击确认按钮会验证两次输入额密码是否相同,如果相同将密码存储起来并启动 显示已加锁界面。在看代码时需要注意三个变量,第一个变量“flag”,flag=0时表示设置密码界面,为1表示确认密码界面。功能按钮在响应事件时,会根据flag值调用不同的方法。

case R.id.button_sure :
if(flag == 0) {
nextStepButtonSure();
} else if(flag == 1) {
affirmButtonSure();
}
break;
}
/**
* 点击“下一步”按钮之后的操作
*/
public void nextStepButtonSure() {
password = passwordEditText.getText().toString();
//更新功能按钮文字为“确定”
Util.updataButtonText(nextStepImageButton, getResources().getString(R.string.ok));
//更新输入框提示信息,提示再次输入密码
Util.setEditViewHint(passwordEditText, getResources().getString(R.string.enter_psw_16_again));
flag = 1;
mIsSetPWD = true;
}
/**
* 点击“确认”按钮之后的操作
*/
public void affirmButtonSure() {
if(passwordEditText.getText().toString().equals(password)) {
if(mIsSetPWD) {
//将密码写入配置文件中
editor.putString("password", password);
editor.commit();
}
if (!isTempLauncher) {
Intent intent = new Intent();
intent.setClass(SetPasswordActivity.this, LockAppsListActivity.class);
startActivity(intent);
}
finish();
} else {
//更新输入框提示信息,提示密码输入错误
Util.setEditViewHint(passwordEditText, getResources().getString(R.string.enter_psw_16_error));
}
}
第二个变量是mIsSetPWD,布尔值,false表示没有在设置密码,true表示在设置密码。非第一次使用软件锁时点击功能按钮会直接执行affirmButtonSure()方法,此时只需要判断输入的密码和配置文件中的密码是否相同即可,所以我加了一个mIsSetPWD变量,默认为false,在点击“下一步”按钮时,此变量设置为true。在执行确认按钮时,会根据这个值来判断是否需要将密码写入配置文件中。第三个变量是isTempLauncher,
当服务检测到栈顶的 Activity 所属应用是被加锁的应用时,会启动输入密码界面。密码输入正确就会执行 finish() 方法,而不再需要启动显示已加锁应用的界面。因此我设置了isTempLauncher 变量(默认false),从服务启动 SetPasswordActivity 时会传递 isTempLauncher 变量且值为true, 在SetPasswordActivity 中会获取isTempLauncher 变量的值。执行affirmButtonSure时会判断 isTempLauncher
的值,为假时会启动显示已加锁应用界面。

上面提到的将密码存储在配置文件中,实际是使用了android一种较轻的数据存储方式---SharedPreferences。它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。存储数据的步骤一般如下:

一、根据Context获取SharedPreferences对象

二、利用SharedPreferences对象的edit()方法获取Editor对象。

三、通过Editor对象存储key-value键值对数据。

四、通过commit()方法提交数据。

public class MainActivity extends Activity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取SharedPreferences对象
Context ctx = MainActivity.this;
SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString("STRING_KEY", "string");
editor.putInt("INT_KEY", 0);
editor.putBoolean("BOOLEAN_KEY", true);
editor.commit();
//返回STRING_KEY的值
Log.d("SP", sp.getString("STRING_KEY", "none"));
//如果NOT_EXIST不存在,则返回值为"none"
Log.d("SP", sp.getString("NOT_EXIST", "none"));
}
}

其中getSharedPreferences方法的两个参数,分别为创建存储数据文件的名称和操作文件的方式,操作文件方式有四种:MODEL_PRIVATE(默认方式)、MODEL_WORLD_READABLE、MODEL_WORLD_WRITEABLE和MODEL_MULTI_PROCESS。使用第一种方式创建的文件只可被所创建的应用访问而中间两种方式创建的文件可以被所有应用访问。

以上模块部分还涉及到数据库SQLite的操作及应用信息收集等知识点。由于篇幅限制不在此贴阐述,数据库SQLite移步这里,获取应用信息请移步这里。

参考

http://www.cnblogs.com/ybc77107/p/3422983.html
android数据存储方式SharedPreferences
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐