本帖最后由 小鲁哥哥 于 2017-4-12 14:33 编辑
Android课程同步笔记day12:Android应用之安全卫士 程序锁
程序锁可以将某一个应用上锁,当进入该程序时需要输入手机防盗密码,UI界面如图所示
在程序锁界面中使用Fragment 控件分别展示未加锁应用和已加锁应用,将一个应用加锁后,此时会将该应用存入到数据库中。当在常用工具界面中打开程序锁服务时,运行在后台的服务监测当前打开的应用,如果打开的应用在数据库中,就说明程序是加锁程序,会弹出输入密码界面,密码输入正确后才能打开应用(密码为手机防盗密码)。
看门狗
看门狗服务顾名思义就是替用户监测手机中的一些信息,这里的看门狗主要是为上面的程序锁功能服务的,它可以在用户点击加锁应用时进入一个输入密码的界面,只有输入密码正确才会进入当前应用中,效果图如图所示:
密码设置和输入界面 上诉功能中只要我们选择某一个应用添加到加锁界面后,并且我们打开了看门狗服务,那么当点击这个应用时就应该输入密码;这里设置密码和输入密码的界面如下图所示;并且在设置密码之前还有一个设置向导的界面
程序锁密码页面结构
根据我们的页面结构图分析来看,首先进入程序锁界面应该判断是否是需要输入密码还是设置密码:
[Java] 纯文本查看 复制代码 public class AppLockSettingActivity extends FragmentActivity {
private static final String TAG = "AppLockSettingActivity";
private TextView mTvTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_lock_setting);
mTvTitle = (TextView) findViewById(R.id.als_tv_title);
// 要么显示密码输入,要么显示密码设置
// 有密码--》密码输入
// 没有密码--》密码设置
String pwd = PreferenceUtils.getString(this, Config.KEY_APP_LOCK_PWD);
if (TextUtils.isEmpty(pwd)) {
// 密码设置
loadPwdManagerFragment();
} else {
// 密码输入
loadPwEnterFragment();
}
}
/**
* 进入密码设置界面
*/
private void loadPwdManagerFragment() {
Log.d(TAG, "进入密码设置");
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.als_container, new PwdManagerFragment());
transaction.commit();
}
/**
* 进入密码输入界面
*/
private void loadPwEnterFragment() {
Log.d(TAG, "进入密码输入");
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.als_container, new PwdEnterFragment());
transaction.commit();
}
public void setAppLockTitle(String title) {
mTvTitle.setText(title);
}
}
创建所有的fragment创建上诉对应的两个fragment以及之前逻辑图中分析所需要用到的fragment,注意需要用supportV4包中的兼容包,兼容低版本。 1.PwdManagerFragment该fragment其实是用来管理需要显示的三个fragment,所以只是作为一个容器来使用和管理;布局文件为
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pwd_manager_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
代码实现
[Java] 纯文本查看 复制代码 public class PwdManagerFragment extends Fragment {
private static final String TAG = "PwdManagerFragment";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_pwd_manager, container,
false);
// 管理显示Fragment
// 默认显示PwdSetupFragment
loadPwdSetupFragment();
return view;
}
//当activity创建的时候回调
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, "onActivityCreated");
// 设置回退栈的监听
doBackStackListener();
// 管理显示Fragment
// 默认显示PwdSetupFragment设置向导界面
loadPwdSetupFragment();
}
private void doBackStackListener() {
final FragmentManager fm = getChildFragmentManager();
fm.addOnBackStackChangedListener(new OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
// 当回退栈发生改变时
// 获得栈顶部的fragment
int count = fm.getBackStackEntryCount();
Log.d(TAG, "回退栈发生改变 count:"+count);
if (count > 0) {
BackStackEntry entry = fm.getBackStackEntryAt(count - 1);
String name = entry.getName();
if ("setup".equals(name)) {
setApplockTitle("密码设置向导");
} else if ("setting".equals(name)) {
setApplockTitle("密码设置");
} else if ("confirm".equals(name)) {
setApplockTitle("密码确认");
}
}
}
});
}
/**设置activity的title*/
public void setApplockTitle(String title) {
AppLockSettingActivity activity = (AppLockSettingActivity) getActivity();
activity.setAppLockTitle(title);
}
/**显示设置向导界面*/
public void loadPwdSetupFragment() {
FragmentManager fm = getChildFragmentManager();
// 开启事务
FragmentTransaction transaction = fm.beginTransaction();
// 设置动画
transaction.setCustomAnimations(0, R.anim.f_exit, R.anim.f_pop_enter,R.anim.f_pop_exit);
// 设置fragment
transaction.replace(R.id.pwd_manager_container, new PwdSetupFragment());
// 添加到回退栈
transaction.addToBackStack("setup");
// 提交事务
transaction.commit();
}
/**显示设置密码界面*/
public void loadPwdSettingFragment() {
FragmentManager fm = getChildFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
// 设置动画
transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit,
R.anim.f_pop_enter, R.anim.f_pop_exit);
transaction.replace(R.id.pwd_manager_container,
new PwdSettingFragment());
// 添加到回退栈
transaction.addToBackStack("setting");
transaction.commit();
}
/**显示确认密码界面*/
public void loadPwdConfirmFragment(String password) {
FragmentManager fm = getChildFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
// 设置动画
transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit,
R.anim.f_pop_enter, R.anim.f_pop_exit);
PwdConfirmFragment fragment = new PwdConfirmFragment();
Bundle args = new Bundle();
args.putString("password", password);
fragment.setArguments(args);
transaction.replace(R.id.pwd_manager_container, fragment);
// 添加到回退栈
transaction.addToBackStack("confirm");
transaction.commit();
}
public void popBack() {
FragmentManager fm = getChildFragmentManager();
fm.popBackStack();
}
}
注意: transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit, R.anim.f_pop_enter, R.anim.f_pop_exit); 代表的是设置每一个fragment切换时的动画,前面两个参数分别代表的是当前展示的fragment从右边进来的时候动画以及出去的动画;而最后两个参数代表的是当前fragment如果存在于back stack回退栈中左边进来的时候以及出去的时候的动画。 回退栈的作用就是可以让activity中的所有fragment可以实现点击返回键的时候直接返回到上一个fragment,不过前提是打开的这个fragment必须通过transcation添加到回退栈。 f_enter.xml: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="100%p"
android:toXDelta="0" >
</translate> f_exit.xml: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:toXDelta="-100%p" >
</translate> f_pop_enter.xml: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="-100%p"
android:toXDelta="0" >
</translate> f_pop_exit.xml: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0"
android:toXDelta="100%p" >
</translate> 密码设置向导fragment 该界面主要是给用户展示如何设置密码,那么需要用到两个api;第一个是设置当前的mPatternView不可以让用户点击;第二个设置一个演示的密码:mPatternView.setPattern(DisplayMode.Animate,"0368"); 界面布局: [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:background="@android:color/black"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="按照以下手势进行密码设置"
android:textColor="#ffffff" />
<com.itheima.zphuanlove.view.LockPatternView
android:id="@+id/fragment_pattern_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="100" />
<Button
android:id="@+id/fragment_btn_next"
style="@style/btnCancelNormal"
android:layout_width="match_parent"
android:layout_margin="8dp"
android:layout_weight="1"
android:text="下一步" /></LinearLayout>[/align][align=left] 完整的代码如下: [Java] 纯文本查看 复制代码 public class PwdSetupFragment extends Fragment implements OnClickListener {
private static final String TAG = "PwdSetupFragment";
private Button mBtnNext;
private LockPatternView mPatternView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pwd_setup, container,
false);
initView(view);
// 设置点击事件
initEvent();
return view;
}
private void initView(View view) {
mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);
mPatternView = (LockPatternView) view
.findViewById(R.id.fragment_pattern_view);
// 设置图案view不可使用,要显示动画
mPatternView.disableInput();
mPatternView.setPattern(DisplayMode.Animate, "0368");
}
private void initEvent() {
mBtnNext.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mBtnNext) {
clickNext();
}
}
private void clickNext() {
// 切换到密码设置的fragment中
PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
fragment.loadPwdSettingFragment();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "manager fragment destroy");
}
} 密码设置fragment 该界面主要是让用户自己输入密码,需要监听用户输入的图案,然后转换成string字符串,通过PwdManagerFragment打开下一个密码确认fragment时传递过去。 界面布局: [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:background="@android:color/black"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="请设置密码"
android:textColor="#ffffff" />
<com.itheima.zphuanlove.view.LockPatternView
android:id="@+id/fragment_pattern_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/fragment_btn_pre"
style="@style/btnCancelNormal"
android:layout_width="match_parent"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text="上一步" />
<Button
android:id="@+id/fragment_btn_next"
style="@style/btnCancelNormal"
android:layout_width="match_parent"
android:layout_marginLeft="4dp"
android:layout_weight="1"
android:text="下一步" />
</LinearLayout>
</LinearLayout> 完整代码: [Java] 纯文本查看 复制代码 public class PwdSettingFragment extends Fragment implements OnClickListener {
private Button mBtnPre;
private Button mBtnNext;
private LockPatternView mPatternView;
private String mPassword;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pwd_setting, container,
false);
initView(view);
// 设置点击事件
initEvent();
return view;
}
private void initView(View view) {
mBtnPre = (Button) view.findViewById(R.id.fragment_btn_pre);
mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);
mPatternView = (LockPatternView) view
.findViewById(R.id.fragment_pattern_view);
}
private void initEvent() {
mBtnPre.setOnClickListener(this);
mBtnNext.setOnClickListener(this);
mPatternView.setOnPatternListener(new OnPatternListener() {
@Override
public void onPatternStart() {
}
@Override
public void onPatternDetected(List<Cell> pattern) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < pattern.size(); i++) {
Cell cell = pattern.get(i);
int p = cell.getRow() * 3 + cell.getColumn();
builder.append(p);
}
mPassword = builder.toString();
}
@Override
public void onPatternCleared() {
mPassword = null;
}
@Override
public void onPatternCellAdded(List<Cell> pattern) {
}
});
}
@Override
public void onClick(View v) {
if (v == mBtnNext) {
clickNext();
} else if (v == mBtnPre) {
clickPre();
}
}
private void clickPre() {
// // 切换到密码设置向导的fragment中
// PwdManagerFragment fragment = (PwdManagerFragment)
// getParentFragment();
// fragment.loadPwdSetupFragment();
// 回退操作
PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
fragment.popBack();
}
private void clickNext() {
if (TextUtils.isEmpty(mPassword)) {
Toast.makeText(getActivity(), "必须去设置密码", Toast.LENGTH_SHORT).show();
return;
}
// 切换到密码确认的fragment中
PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
fragment.loadPwdConfirmFragment(mPassword);
}
} 重复密码确认fragment
该界面主要点在于获取到设置密码传递过来的密码数据;然后监听当前用户输入的重复密码,在点击设置完成按钮的时候进行比对。 布局文件:
[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:background="@android:color/black"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:text="请确认密码"
android:textColor="#ffffff" />
< com.itheima.zphuanlove.view.LockPatternView
android:id="@+id/fragment_pattern_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/fragment_btn_pre"
style="@style/btnCancelNormal"
android:layout_width="match_parent"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text="上一步" />
<Button
android:id="@+id/fragment_btn_next"
style="@style/btnCancelNormal"
android:layout_width="match_parent"
android:layout_marginLeft="4dp"
android:layout_weight="1"
android:text="设置完成" />
</LinearLayout>
</LinearLayout>
完整代码:
[Java] 纯文本查看 复制代码 public class PwdConfirmFragment extends Fragment implements OnClickListener{
private Button mBtnPre;
private Button mBtnNext;
private LockPatternView mPatternView;
private String mConfirmPassword;
private String mPassword;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
mPassword = arguments.getString("password");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pwd_confirm, container,
false);
initView(view);
// 设置点击事件
initEvent();
return view;
}
private void initView(View view) {
mBtnPre = (Button) view.findViewById(R.id.fragment_btn_pre);
mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);
mPatternView = (LockPatternView) view
.findViewById(R.id.fragment_pattern_view);
}
private void initEvent() {
mBtnPre.setOnClickListener(this);
mBtnNext.setOnClickListener(this);
mPatternView.setOnPatternListener(new OnPatternListener() {
@Override
public void onPatternStart() {
}
@Override
public void onPatternDetected(List<Cell> pattern) {
// 密码获得
// 记录密码
StringBuilder builder = new StringBuilder();
for (int i = 0; i < pattern.size(); i++) {
Cell cell = pattern.get(i);
int p = cell.getRow() * 3 + cell.getColumn();
builder.append(p);
}
mConfirmPassword = builder.toString();
}
@Override
public void onPatternCleared() {
mConfirmPassword = null;
}
@Override
public void onPatternCellAdded(List<Cell> pattern) {
}
});
}
@Override
public void onClick(View v) {
if (v == mBtnNext) {
clickNext();
} else if (v == mBtnPre) {
clickPre();
}
}
private void clickPre() {
// 切换到密码设置的fragment中
// PwdManagerFragment fragment = (PwdManagerFragment)
// getParentFragment();
// fragment.loadPwdSettingFragment();
PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
fragment.popBack();
}
private void clickNext() {
if (TextUtils.isEmpty(mConfirmPassword)) {
Toast.makeText(getActivity(), "必须去设置确认密码", Toast.LENGTH_SHORT)
.show();
return;
}
if (!mConfirmPassword.equals(mPassword)) {
Toast.makeText(getActivity(), "两次密码不一致", Toast.LENGTH_SHORT).show();
return;
}
// 密码设置完成,进行其他跳转
// Toast.makeText(getActivity(), "密码设置完成,进行其他跳转", Toast.LENGTH_SHORT)
// .show();
//
// 存储密码
PreferenceUtils.setString(getActivity(), Config.KEY_APP_LOCK_PWD,
mPassword);
Intent intent = new Intent(getActivity(), AppLockActivity.class);
getActivity().startActivity(intent);
getActivity().finish();
}
}
密码输入界面fragment
当前面的设置密码一系列逻辑实现后,当我们从常用工具点击密码锁再次进来的 时候就应该弹出设置密码的fragment。主要核心点就是判断输入的密码与我们保存在sp中的密码是否一致来进行比对。 布局文件:
[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:background="@android:color/black"
android:orientation="vertical" >
<com.itheima.zphuanlove.view.LockPatternView
android:id="@+id/fragment_pattern_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:layout_weight="100" />
</LinearLayout>
完整代码:
[Java] 纯文本查看 复制代码 public class PwdEnterFragment extends Fragment {
private LockPatternView mPatternView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pwd_enter, container,
false);
initView(view);
initEvent();
return view;
}
private void initView(View view) {
mPatternView = (LockPatternView) view
.findViewById(R.id.fragment_pattern_view);
// 设置title显示
AppLockSettingActivity activity = (AppLockSettingActivity) getActivity();
activity.setAppLockTitle("密码输入");
}
private void initEvent() {
mPatternView.setOnPatternListener(new OnPatternListener() {
@Override
public void onPatternStart() {
}
@Override
public void onPatternDetected(List<Cell> pattern) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < pattern.size(); i++) {
Cell cell = pattern.get(i);
int p = cell.getRow() * 3 + cell.getColumn();
builder.append(p);
}
String password = builder.toString();
// 比对密码
String pwd = PreferenceUtils.getString(getActivity(),
Config.KEY_APP_LOCK_PWD);
if (!pwd.equals(password)) {
// 不同
mPatternView.setDisplayMode(DisplayMode.Wrong);
return;
}
// 正确,页面跳转
Intent intent = new Intent(getActivity(), AppLockActivity.class);
getActivity().startActivity(intent);
getActivity().finish();
}
@Override
public void onPatternCleared() {
}
@Override
public void onPatternCellAdded(List<Cell> pattern) {
}
});
}
}
程序锁activity展示界面UI展示界面:
代码如下:
[Java] 纯文本查看 复制代码 public class SegmentView extends LinearLayout implements View.OnClickListener {
private TextView mTvLeft;
private TextView mTvRight;
private OnCheckListener mListener;
private boolean mLeftSelected;
public SegmentView(Context context) {
this(context, null);
}
public SegmentView(Context context, AttributeSet attrs) {
super(context, attrs);
// /挂载xml
View.inflate(context, R.layout.view_segment, this);
mTvLeft = (TextView) findViewById(R.id.segment_tv_left);
mTvRight = (TextView) findViewById(R.id.segment_tv_right);
// 设置默认选中
mTvLeft.setSelected(true);
mTvRight.setSelected(false);
mLeftSelected = true;
// 初始化事件
initEvent();
}
private void initEvent() {
mTvLeft.setOnClickListener(this);
mTvRight.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == mTvLeft) {
// 如果左侧没有被选中 ,才能被选中
if (mLeftSelected) {
return;
}
// 点击左侧,让左侧选中
mTvLeft.setSelected(true);
mTvRight.setSelected(false);
mLeftSelected = true;
// 改变activity UI显示 ---》 控件的存在依赖于activity业务逻辑
// 接口回调
if (mListener != null) {
mListener.onChecked(mTvLeft, true);
}
} else if (v == mTvRight) {
// 如果右侧没有被选中 ,才能被选中
if (!mLeftSelected) {
return;
}
// 点击右侧,让右侧选中
mTvLeft.setSelected(false);
mTvRight.setSelected(true);
mLeftSelected = false;
// 改变activity UI显示
// 接口回调
if (mListener != null) {
mListener.onChecked(mTvRight, false);
}
}
}
/**
* 设置监听器
*
* @param listener
*/
public void setOnCheckListener(OnCheckListener listener) {
this.mListener = listener;
}
public interface OnCheckListener {
/**
* 当选中时
*
* @param v
* :选中的view
* @param leftSelected
* :是否左侧选中
*/
void onChecked(View v, boolean leftSelected);
}
}
主要涉及到一个接口回调的实现,目的是当点击对应的加锁和未加锁时需要让activity界面下方显示对应的界面。 程序锁下方对应的界面为listview,这里直接用两个listview来交替实现,当然有兴趣的同学也可以通过fragment去实现。
AppLockActivity的布局为: [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" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/title_bg" >
< com.itheima.zphuanlove.view.SegmentView
android:id="@+id/al_segmentview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
<TextView
android:id="@+id/al_tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#55000000"
android:padding="4dp"
android:text="未加锁"
android:textColor="#ffffff" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ListView
android:id="@+id/al_listview_lock"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" >
</ListView>
<ListView
android:id="@+id/al_listview_unlock"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
</LinearLayout> 初始化控件并先将分段控件的点击事件给先实现好: [Java] 纯文本查看 复制代码 public class AppLockActivity extends Activity {
private SegmentView mSegmentView;
private ListView mLockListView;
private ListView mUnLockListView;
private TextView mTvTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_lock);
initView();
initEvent();
}
private void initView() {
mSegmentView = (SegmentView) findViewById(R.id.al_segmentview);
mLockListView = (ListView) findViewById(R.id.al_listview_lock);
mUnLockListView = (ListView) findViewById(R.id.al_listview_unlock);
mTvTitle = (TextView) findViewById(R.id.al_tv_title);
}
private void initEvent() {
// 分段控件左右选中时,会影响下面布局的显示
mSegmentView.setOnCheckListener(new OnCheckListener() {
@Override
public void onChecked(View v, boolean leftSelected) {
Toast.makeText(AppLockActivity.this,
leftSelected ? "左侧选中" : "右侧选中", Toast.LENGTH_SHORT)
.show();
if (leftSelected) {
// 显示未加锁的
mLockListView.setVisibility(View.GONE);
mUnLockListView.setVisibility(View.VISIBLE);
} else {
// 显示已经加锁的
mLockListView.setVisibility(View.VISIBLE);
mUnLockListView.setVisibility(View.GONE);
}
}
});
}
} 程序锁页面Adpater实现接下来就需要通过adpater将数据展示出来进行展示,由于这里有两个listview,所以一个adapter需要进行一些判断才可以实现是加锁还是未加锁的,然后分别传入不同的数据来进行不同的界面展示。 这里首先可以通过制造假数据的形式来先测试界面
[Java] 纯文本查看 复制代码 private void initData() {
// 加载list数据 --假数据展示
mLockDatas = new ArrayList<AppInfo>();
for (int i = 0; i < 30; i++) {
AppInfo bean = new AppInfo();
bean.name = "加锁的程序-" + i;
mLockDatas.add(bean);
}
mUnlockDatas = new ArrayList<AppInfo>();
for (int i = 0; i < 30; i++) {
AppInfo bean = new AppInfo();
bean.name = "未加锁的程序-" + i;
mUnlockDatas.add(bean);
}
// 给未加锁的设置adapter
mUnlockAdapter = new ApplockAdapter(false);
mUnLockListView.setAdapter(mUnlockAdapter);
// 给已加锁的设置adapter
mLockAdapter = new ApplockAdapter(true);
mLockListView.setAdapter(mLockAdapter);
}
private class ApplockAdapter extends BaseAdapter {
private boolean mLocked;
public ApplockAdapter(boolean locked) {
this.mLocked = locked;
}
@Override
public int getCount() {
if (mLocked) {
// 已经上锁的
if (mLockDatas != null) {
mTvTitle.setText("加锁程序(" + mLockDatas.size() + ")");
return mLockDatas.size();
}
mTvTitle.setText("加锁程序(0)");
} else {
// 未上锁的
if (mUnlockDatas != null) {
mTvTitle.setText("未加锁程序(" + mUnlockDatas.size() + ")");
return mUnlockDatas.size();
}
mTvTitle.setText("未加锁程序(0)");
}
return 0;
}
@Override
public Object getItem(int position) {
if (mLocked) {
// 已经上锁的
if (mLockDatas != null) {
return mLockDatas.get(position);
}
} else {
// 未上锁的
if (mUnlockDatas != null) {
return mUnlockDatas.get(position);
}
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
// 没有复用
convertView = View.inflate(AppLockActivity.this,
R.layout.item_app_lock, null);
holder = new ViewHolder();
convertView.setTag(holder);
holder.ivIcon = (ImageView) convertView
.findViewById(R.id.item_al_iv_icon);
holder.ivLock = (ImageView) convertView
.findViewById(R.id.item_al_iv_lock);
holder.tvName = (TextView) convertView
.findViewById(R.id.item_al_tv_name);
} else {
// 有复用
holder = (ViewHolder) convertView.getTag();
}
// 设置数据
AppInfo bean = null;
if (mLocked) {
bean = mLockDatas.get(position);
} else {
bean = mUnlockDatas.get(position);
}
if (bean.icon == null) {
holder.ivIcon.setImageResource(R.drawable.ic_default);
} else {
holder.ivIcon.setImageDrawable(bean.icon);
}
holder.tvName.setText(bean.name);
return convertView;
}
}
private static class ViewHolder {
ImageView ivIcon;
TextView tvName;
ImageView ivLock;
} 这里的javabean可以直接复用之前在软件管家和进程管理里面使用过的javabean。
数据库的创建为了记录加锁的应用程序,这里使用数据库的方式来存储;首先创建数据库: [Java] 纯文本查看 复制代码 public class AppLockDBHelper extends SQLiteOpenHelper {
public AppLockDBHelper(Context context) {
super(context, AppLockDB.NAME, null, AppLockDB.VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 新建表
db.execSQL(AppLockDB.TableApplock.SQL_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public interface AppLockDB {
String NAME = "applock.db";
int VERSION = 1;
public interface TableApplock {
String TABLE_NAME = "t_applock";
String COLUMN_ID = "_id";
String COLUMN_PKG = "pkg";// 用来记录上锁的应用的包名
String SQL_CREATE_TABLE = "create table " + TABLE_NAME + "("
+ COLUMN_ID + " integer primary key autoincrement,"
+ COLUMN_PKG + " text unique" + ")";
}
} 创建一个名为:applock.db的数据库,里面有一张t_applock的表,两个字段一个id一个pkg。
数据库dao的实现实现数据库的增删改查 [Java] 纯文本查看 复制代码 public class AppLockDao {
private AppLockDBHelper mHelper;
public AppLockDao(Context context) {
mHelper = new AppLockDBHelper(context);
}
/**
* 添加数据
*
* @param packageName
* @return
*/
public boolean add(String packageName) {
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(AppLockDB.TableApplock.COLUMN_PKG, packageName);
long insert = db
.insert(AppLockDB.TableApplock.TABLE_NAME, null, values);
db.close();
return insert != -1;
}
/**
* 删除
*
* @param packageName
* @return
*/
public boolean delete(String packageName) {
SQLiteDatabase db = mHelper.getWritableDatabase();
String whereClause = AppLockDB.TableApplock.COLUMN_PKG + "=?";
String[] whereArgs = new String[] { packageName };
int delete = db.delete(AppLockDB.TableApplock.TABLE_NAME, whereClause,
whereArgs);
db.close();
return delete > 0;
}
/**
* 查询是否上锁
*
* @param packageName
* @return
*/
public boolean findLock(String packageName) {
SQLiteDatabase db = mHelper.getReadableDatabase();
String sql = "select count(_id) from "
+ AppLockDB.TableApplock.TABLE_NAME + " where "
+ AppLockDB.TableApplock.COLUMN_PKG + "=?";
Cursor cursor = db.rawQuery(sql, new String[] { packageName });
int count = 0;
if (cursor != null) {
if (cursor.moveToNext()) {
count = cursor.getInt(0);
}
cursor.close();
}
db.close();
return count != 0;
}
} 创建测试类进行测试 [Java] 纯文本查看 复制代码 public class TestAppLock extends AndroidTestCase {
public void testAdd() {
AppLockDao dao = new AppLockDao(getContext());
boolean add = dao.add("com.abc");
assertEquals(true, add);
}
public void testDelete() {
AppLockDao dao = new AppLockDao(getContext());
boolean delete = dao.delete("com.abc");
assertEquals(true, delete);
}
public void testFind() {
AppLockDao dao = new AppLockDao(getContext());
boolean find = dao.findLock("com.abc");
assertEquals(true, find);
}
}
|