我正在开发一个应用程序,当用户离开应用程序并返回时(无论是通过屏幕锁定,还是通过后面或主页按钮返回主屏幕),需要显示密码屏幕。我使用以下方法工作:
启动活动将在启动时调用密码检查,并且每个活动都将以下功能添加到其onPause方法中:
@Override
public void onPause() {
super.onPause();
if (!isFinishing()) {
new PasscodeCheckTask(this.getApplicationContext(),this).execute();
}
}
PassocdeCheckTask如下所示。它会检查屏幕是否已关闭或应用程序是否已不在后台
public class PasscodeCheckTask extends AsyncTask<Void, Void, Boolean> {
public static final int CHECK_PASSCODE = 0;
private Context mActivityApplicationContext;
private Context mActivityContext;
public PasscodeCheckTask(Context applicationContext, Context activityContext){
mActivityApplicationContext = applicationContext;
mActivityContext = activityContext;
}
@Override
protected Boolean doInBackground(Void... params) {
Boolean result = false;
if (!((PowerManager)mActivityApplicationContext.getSystemService(android.content.Context.POWER_SERVICE)).isScreenOn() ||
!isAppOnForeground(mActivityApplicationContext)) {
result = true;
}
return result;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
// Start passcode activity to check for passcode
/* CODE HERE */
((Activity)mActivityContext).startActivityForResult(intent, CHECK_PASSCODE);
}
}
protected boolean isAppOnForeground(final Context context) {
List<RunningAppProcessInfo> appProcesses = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (RunningAppProcessInfo appProcess : appProcesses) {
if ((appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) &&
appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
Passcode活动在完成后完成,如果密码没有通过,调用活动将moveTaskToBackground(true)。这个系统运行得很漂亮,直到我在带有mikg ROM的HTC Evo上试用它。出于某种原因,appProcess.importance从未显示为IMPORTANCE_FOREGROUND。它始终是IMPORTANCE_BACKGROUND。因此,即使应用程序从未进入后台,也始终会显示密码。
我在那部手机上尝试了DropBox(它也有密码锁),而且效果很好。我似乎无法找到一种不同的方式来了解应用程序何时进入后台,或者是否从后台带回来。关于如何使这项工作的任何想法?
答案 0 :(得分:4)
在每个活动的onStop()
中,使用离开活动的时间更新静态数据成员。在每个活动的onStart()
中,检查该时间,如果超过某个超时阈值,则显示您的身份验证活动。允许用户设置超时值,这样如果他们不想每隔几秒就被打扰一次,他们就可以控制它。
答案 1 :(得分:1)
我喜欢基于时间的方法,我一直在努力让这个以一种很好的方式工作。基于时间的方法效果很好。我上了一堂课以便于使用。
public class PinCodeCheck {
private static long INIT_TIME = 0;
private static PinCodeCheck ref = null;
private static SharedPreferences values = null;
private PinCodeCheck(Context context){
values = context.getSharedPreferences("com.example.xxx", 0); //use your preferences file name key!
}//end constructor
public static synchronized PinCodeCheck getInstance(Context context) {
if (ref == null){
ref = new PinCodeCheck(context);
}
return ref;
}//end method
public void init(){
PinCodeCheck.INIT_TIME = System.currentTimeMillis();
}//end method
public void forceLock(){
PinCodeCheck.INIT_TIME = 0;
}//end method
public boolean isLocked(){
long currentTime = System.currentTimeMillis();
long threshold = values.getLong(Keys.PASSWORD_PROTECT_TIMEOUT, 30000); // check here, might change in between calls
if (currentTime - PinCodeCheck.INIT_TIME > threshold){
return true;
}
return false;
}//end method
}//end class
<强> USAGE 强>
private static PinCodeCheck check = PinCodeCheck.getInstance(context);
@Override
public void onResume() {
super.onResume();
if (check.isLocked()) {
showDialog();
}
}//end method
@Override
public void onPause() {
super.onPause();
check.init();
}//end method