标签: 应用锁

Android开发之应用锁解锁方式:指纹和密码

先上效果图:
主要实现的是通过自定义密码或者指纹,给应用锁进行解锁,然后进入APP。

%title插图%num %title插图%num
主要代码:LoginActivity.java
package com.fyang21117.rdiot1.second;

import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.fyang21117.rdiot1.FingerprintUtil;
import com.fyang21117.rdiot1.KeyguardLockScreenManager;
import com.fyang21117.rdiot1.MainActivity;
import com.fyang21117.rdiot1.R;
import com.fyang21117.rdiot1.core.FingerprintCore;

public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

private FingerprintCore mFingerprintCore;
private KeyguardLockScreenManager mKeyguardLockScreenManager;//指纹管理
private Toast mToast;
private Handler mHandler = new Handler(Looper.getMainLooper());//主线程
private EditText editText;
private String string;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
setTitle(“应用锁”);

initFingerprintCore();

Button psw_login = findViewById(R.id.psw_login);
Button use_fingerprint = findViewById(R.id.use_fingerprint);
editText = findViewById(R.id.unlock_num);
psw_login.setOnClickListener(this);
use_fingerprint.setOnClickListener(this);
}

@Override
public void onClick(View v) {
final int viewId = v.getId();
switch (viewId) {
case R.id.use_fingerprint:
//调用非活动布局的控件
View view= getLayoutInflater().inflate(R.layout.fingerprint_dialog, null);
final MyDialog mMyDialog= new MyDialog(this, 0, 0, view, R.style.DialogTheme);
Button cancel_fingerprint = view.findViewById(R.id.cancel_unlock);
mMyDialog.setCancelable(true);
mMyDialog.show();
startFingerprintRecognition();
cancel_fingerprint.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mMyDialog.dismiss();
}
});
break;
case R.id.psw_login:
string =editText.getText().toString();
if(string.equals(“1028″))
MainActivity.actionStart(this);
else
Toast.makeText(this,”Unlocking failed!Please input again!”,Toast.LENGTH_SHORT).show();
break;
}
}
/*** 指纹识别初始化*/
private void initFingerprintCore() {
mFingerprintCore = new FingerprintCore(this);
mFingerprintCore.setFingerprintManager(mResultListener);
mKeyguardLockScreenManager = new KeyguardLockScreenManager(this);
}

/*** 进入系统设置指纹界面*/
private void enterSysFingerprintSettingPage() {
FingerprintUtil.openFingerPrintSettingPage(this);
}
private void startFingerprintRecognitionUnlockScreen() {
if (mKeyguardLockScreenManager == null) {
return;
}
if (!mKeyguardLockScreenManager.isOpenLockScreenPwd()) {
FingerprintUtil.openFingerPrintSettingPage(this);
return;
}
mKeyguardLockScreenManager.showAuthenticationScreen(this);
}

/*** 开始指纹识别*/
private void startFingerprintRecognition() {
if (mFingerprintCore.isSupport()) {
if (!mFingerprintCore.isHasEnrolledFingerprints()) {
toastTipMsg(R.string.fingerprint_recognition_not_enrolled);
FingerprintUtil.openFingerPrintSettingPage(this);
return;
}

toastTipMsg(R.string.fingerprint_recognition_tip);
if (mFingerprintCore.isAuthenticating()) {
toastTipMsg(R.string.fingerprint_recognition_authenticating);
} else {
mFingerprintCore.startAuthenticate();
}
} else {
toastTipMsg(R.string.fingerprint_recognition_not_support);
}
}

private void IntoActivity() {
MainActivity.actionStart(this);//识别成功
}

private FingerprintCore.IFingerprintResultListener mResultListener
= new FingerprintCore.IFingerprintResultListener() {
@Override
public void onAuthenticateSuccess() {
toastTipMsg(R.string.fingerprint_recognition_success);
IntoActivity();
}
@Override
public void onAuthenticateFailed(int helpId) {
toastTipMsg(R.string.fingerprint_recognition_failed);
}
@Override
public void onAuthenticateError(int errMsgId) {
toastTipMsg(R.string.fingerprint_recognition_error);
}
@Override
public void onStartAuthenticateResult(boolean isSuccess) {
}
};

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == KeyguardLockScreenManager.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
// Challenge completed, proceed with using cipher
if (resultCode == RESULT_OK) {
toastTipMsg(R.string.sys_pwd_recognition_success);
} else {
toastTipMsg(R.string.sys_pwd_recognition_failed);
}
}
}

private void toastTipMsg(int messageId) {
if (mToast == null) {
mToast = Toast.makeText(this, messageId, Toast.LENGTH_SHORT);
}
mToast.setText(messageId);
mToast.cancel();
mHandler.removeCallbacks(mShowToastRunnable);
mHandler.postDelayed(mShowToastRunnable, 0);
}

private void toastTipMsg(String message) {
if (mToast == null) {
mToast = Toast.makeText(this, message, Toast.LENGTH_LONG);
}
mToast.setText(message);
mToast.cancel();
mHandler.removeCallbacks(mShowToastRunnable);
mHandler.postDelayed(mShowToastRunnable, 200);
}

private Runnable mShowToastRunnable = new Runnable() {
@Override
public void run() {
mToast.show();
}
};

@Override
protected void onDestroy() {
if (mFingerprintCore != null) {
mFingerprintCore.onDestroy();
mFingerprintCore = null;
}
if (mKeyguardLockScreenManager != null) {
mKeyguardLockScreenManager.onDestroy();
mKeyguardLockScreenManager = null;
}
mResultListener = null;
mShowToastRunnable = null;
mToast = null;
super.onDestroy();
}
}
activity_login.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”>

<LinearLayout
android:id=”@+id/digital_layout”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
android:layout_gravity=”center_vertical”
android:gravity=”center_vertical”>

<EditText
android:id=”@+id/unlock_num”
android:layout_width=”270dp”
android:layout_height=”wrap_content”
android:layout_gravity=”center_horizontal”
android:gravity=”center_horizontal”
android:inputType=”number”
android:hint=”input your unlocking nums:”
android:textAllCaps=”false”/>
<Button
android:id=”@+id/psw_login”
android:layout_width=”270dp”
android:layout_height=”wrap_content”
android:layout_gravity=”center_horizontal”
android:gravity=”center_horizontal”
android:text=”@string/login2″
android:textAllCaps=”false”
android:textSize=”20sp”/>
<Button
android:id=”@+id/use_fingerprint”
android:layout_width=”270dp”
android:layout_height=”wrap_content”
android:layout_gravity=”center_horizontal”
android:gravity=”center_horizontal”
android:text=”@string/use_fingerprint”
android:textAllCaps=”false”
android:textSize=”20sp”/>
</LinearLayout>

</LinearLayout>
解锁只是 个人工程的一部分,具体可参考下面链接:
完整代码见:https://github.com/fyang21117/RDIOT1

Android应用锁实现

为了不让别人查看隐私,我们经常会对各种应用进行加锁。目前应用市场上应用锁有很多,各种安全类软件都有这个功能。

对于第三方软件,其实现应用锁的基本原理就是不断的轮询栈顶的应用包名,如果是在加锁名单里的应用,则会弹出解锁界面。这种方式的缺点比较明显,应用实际上已经启动起来了,只是强行在上面又盖了一层界面,同时也避免不了会先看到应用的界面然后才弹出解锁界面的问题。具体实现可查看http://blog.csdn.net/turkeycock/article/details/50521103

如果有root权限,就可以避免该这些问题。下面看下具有系统权限的app的应用锁实现方案。

应用锁从用户的角度看是对应用进行加锁,但是从系统的角度看,其实是对activity的拦截。

其实现原理比较简单,在startActivity的过程中,我们注意到

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {

boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
resultRecord, resultStack, options);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);

if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}


if (abort) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
return START_SUCCESS;
}

}
这里有个abort变量,如果其为true,那么就直接返回了,不会再去继续startActivity的流程。
看下赋值的地方

abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);

调用了ams的mController的activityStarting方法,该方法返回是否拦截activity的启动。
mController是IActivityController类型的对象,通过IActivityController实现对activity的拦截。
因此只要mController的activityStarting返回false,abor就会t设置为true,activity将不会启动,这时我们可以启动加锁页面,如果用户输入了正确的密码,再去把要启动的activity启动起来,达到应用锁的目的。

IActivityController.aidl
就是通过这个aidl文件来实现系统层的应用锁功能,看下该文件的具体内容
frameworks/base/core/java/android/app/IActivityController.java
/**
* Testing interface to monitor what is happening in the activity manager
* while tests are running.  Not for normal application development.
* {@hide}
*/
interface IActivityController
{
/**
* The system is trying to start an activity.  Return true to allow
* it to be started as normal, or false to cancel/reject this activity.
*/
boolean activityStarting(in Intent intent, String pkg);

/**
* The system is trying to return to an activity.  Return true to allow
* it to be resumed as normal, or false to cancel/reject this activity.
*/
boolean activityResuming(String pkg);

/**
* An application process has crashed (in Java).  Return true for the
* normal error recovery (app crash dialog) to occur, false to kill
* it immediately.
*/
boolean appCrashed(String processName, int pid,
String shortMsg, String longMsg,
long timeMillis, String stackTrace);

/**
* Early call as soon as an ANR is detected.
*/
int appEarlyNotResponding(String processName, int pid, String annotation);

/**
* An application process is not responding.  Return 0 to show the “app
* not responding” dialog, 1 to continue waiting, or -1 to kill it
* immediately.
*/
int appNotResponding(String processName, int pid, String processStats);

/**
* The system process watchdog has detected that the system seems to be
* hung.  Return 1 to continue waiting, or -1 to let it continue with its
* normal kill.
*/
int systemNotResponding(String msg);
}

这里提供了一系列的方法去监听应用状态,包括activity的启动,resume,无响应等。该文件时hide的,不对第三方应用开放。应用锁主要关注
boolean activityStarting(in Intent intent, String pkg);
pkg是要启动的activity的包名,在这个方法里我们可以去判断这个pkg是否需要加锁,如果需要则返回false拦截该activity的启动,如果不需要加锁则返回true继续startActivity的过程。

ams中也提供了设置该监听器的方法

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setActivityController(IActivityController controller, boolean imAMonkey) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
“setActivityController()”);
synchronized (this) {
mController = controller;
mControllerIsAMonkey = imAMonkey;
Watchdog.getInstance().setActivityController(controller);
}
}
通过IActivityController可以实现真正的应用锁。

 

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速