Android 应用锁/程序锁(APPLock)的实现 http://shigongbo.blog.163.com/blog/static/976090201452572535715

转自:http://shigongbo.blog.163.com/blog/static/976090201452572535715


今天看到某Android安全软件有一个安全锁的功能,使用的时候,点击返回竟然是无效的,必须要用户输入密码!这用户体验也太差了!在网上查了一下,发现许多人都是在Activity中显示解锁画面,并屏蔽返回键。我感觉这样用户体验很差,于是就想自己实现一个。现在把主要思路和代码分享一下。

其实这个程序核心代码很少,不超过一百行就搞定。不过其中牵扯到的Android知识点很多,现在听我从头道来。
我们先来解释一下APPLock的原理。
用户启动APPLock,此时会列出所有的应用程序,选择要Lock的应用,将此应用的信息(包名)保存到数据库或文件。
并启动一个Service,我们称其为LockService,在后台一直监听,查看要Lock的应用是否被启动。
当用户启动了要Lock的应用,LockService就会察觉到,此时显示密码界面,让用户输入密码,密码正确后,密码界面消失。
如果密码界面正在显示的时候,用户点击返回,会怎么样?那肯定是密码界面消失,要启动的应用显示出来,这就不能达到应用锁的效果,所以开发者选择了在密码界面屏蔽返回键的方式。体验太差!

首先,要解决的就是怎么避免使用Activity显示解锁画面并屏蔽返回键这种不好的用户体验。
既要显示画面,又要不屏蔽返回键,怎么实现呢?
Service!对,就是在Service中显示画面。使用WindowManager加载layout的方式,让解锁画面显示在最前端。

View mLockView;
TextView mTextView;
WindowManager mWindowManager = null;

mContext = getApplicationContext();

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_FULLSCREEN |
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.RGBA_8888);
        params.gravity = (Gravity.CENTER);

        mLockView= layoutInflater.inflate(R.layout.lock_app_service, null);
        mTextView = (TextView) mLockView.findViewById(R.id.service_input_pwd);

        if (mWindowManager == null) {
            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        }

        if (mWindowManager != null && mLockView!= null) {
            mWindowManager.addView(mLockView, params);
        }

把这段加到LockService中,它会显示一个覆盖屏幕的画面,也就是你xml定义的文件lock_app_service。
要使用这个功能,你还要在Manifest中添加权限

<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />


这样这个画面运行的时候就会在最前端覆盖整个屏幕了。
正式因为这是用WindowManager在最前端画出的,所以当前运行的Activity并不受影响,还是在正常运行,并不会改变生命周期,你可以在onPause中打印Log来印证,你会发现onPause并不会调用。

现在再看看怎么检测要Lock的应用开始启动了。Android中启动一个Activity的时候并没有对应的广播事件。启动一个Activity,首先是发送Intent,ActivityManagerService(AMS)会处理这个Intent。首先AMS会检测这个要启动的Activity是否存在,然后判断判断启动者是否有权限启动被启动的Activity(根据 PID和UID ),然后把被启动的Activity压入栈中。
我们就是根据这一特点,来判断刚刚启动的Activity是否为被Lock的。

ActivityManager mActivityManager;

mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);

ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity; String packageName = topActivity.getPackageName(); String className = topActivity.getClassName(); Log.v("LockService", "packageName == " + packageName); Log.v("LockService", "className == " + className);

从Log信息可以发现,此时出现的肯定是当前正在运行的应用的包名和Activity名字。
要运行这个功能,需要添加权限

<uses-permission android:name="android.permission.GET_TASKS"/>

OK,核心功能就只有这么几行,是不是不超过一百行!

剩下的工作就是界面配置和Service启动方面的了。我在这里只说一下思路。
1. 启动LockActivity。
这是一个含有list的界面,外加一个Lock开关按钮。当开关On状态,启动LockService。Off状态关闭LockService。
list中列出所有的APP应用。获取已经安装应用,代码如下

        List<PackageInfo> packages = getPackageManager().getInstalledPackages(0);         for(int i=0;i<packages.size();i++) {             PackageInfo packageInfo = packages.get(i);             Log.v("LockActivity", "packageInfo.packageName == " + packageInfo.packageName);             Log.v("LockActivity", "packageInfo.versionName == " + packageInfo.versionName);             Log.v("LockActivity", "packageInfo.versionCode == " + packageInfo.versionCode);         }

当用户点击list中的Item时候,将该应用的信息保存到数据库或者文件中。
2. LockService运行后,在其中写一个线程,不停地循环判断Activity栈顶是不是要Lock的Activity。
是,则显示密码界面,并保存当前状态。否则continue。
当用户输入了正确的密码,这则消失掉界面,代码为
mWindowManager.removeView(mLockView);
这样就显示了真正的Activity了。
当用户点击了返回,由于我们的LockService中的WindowManager并没有改变实际的启动Activity的生命周期,所以返回键还是作用在实际Activity上了,所以实际Activity消失,此时根据后台的循环判断,最上次的Activity栈已经不是要被Lock的,根据刚才保存的状态,同样将密码界面消失掉。

OK。大功告成。整个应用程序安全管家就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值