涉及 AlarmManager 的方法没有按照我需要的方式运行
Method involving AlarmManager isn't functioning the way I need it to
我有一个名为 lock 的方法,它设置随机锁屏密码并在按下按钮时使用 DevicePolicyManager 锁定屏幕。就在 phone 锁定之前,此锁定方法还会安排警报在一定时间后响起。此警报调用一种方法将锁屏密码重置为存储值。
我遇到的问题是,每当按下调用我的锁定方法的按钮时,phone 就会像它应该的那样锁定,它还会像它应该的那样将锁屏密码重置为随机密码,所以在 phone 锁定后,用户可以尝试解锁它并弹出只接受随机密码的锁定屏幕。但是,如果用户在锁定屏幕上按回键,然后再次尝试解锁 phone,则锁定屏幕密码会立即设置为存储的 pin 值。如果用户再次锁定 phone 并尝试解锁它,也会发生这种情况。我希望在经过一定时间后而不是立即重置密码。
我已经在另一个 class 中配置了 DeviceAdmin 接收器。
我是否遗漏了 AlarmManager 中的某些内容或在我的锁定方法中做错了什么?
请注意,我是用这种方法更改实际设备的锁屏密码,并不是我自己制作锁屏。
按下我的按钮时调用的锁定方法
final Random rand=new Random();
public void lock(View v) {
int diceRoll;
setMins();
//this section schedules an alarm that calls my overridden broadcast receiver in this class
Intent alarmIntent=new Intent(this, AlarmBroadCastReceiver.class);
PendingIntent pendIntent=PendingIntent.getBroadcast(this, 1, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alMgr=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
alMgr.cancel(pendIntent);
alMgr.set(AlarmManager.ELAPSED_REALTIME, (time * 60000), pendIntent);
diceRoll=rand.nextInt(9999)+1;
if (mgr.isAdminActive(cn))
{
mgr.setPasswordQuality(cn, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
mgr.setPasswordMinimumLength(cn, 0);
//this sets the lock screen password to a random one
mgr.resetPassword(Integer.toString(diceRoll), 0);
mgr.lockNow();
}
else {
Intent intent =
new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, cn);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
getString(R.string.device_admin_explanation));
startActivity(intent);
}
}
这是我的 resetPasswordAgain 方法,从这个 class 覆盖的 BroadcastReceiver 调用。此方法将锁屏密码重置为存储值
public void resetPasswordAgain()
{
mgr.setPasswordQuality(cn, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
mgr.setPasswordMinimumLength(cn, 0);
mgr.resetPassword(SetPinDialogFragment.pin, 0);
}
来自此 class
的覆盖广播接收器
BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
resetPasswordAgain();
}
};
@Override
protected void onDestroy()
{
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
我在另一个 class 中也有一个基本的广播接收器,但是它被上面显示的覆盖了
public class AlarmBroadCastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
context.sendBroadcast(new Intent("CALL_METHOD"));
}
}
清单,以备不时之需
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fbtc141.test3">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
android:versionCode="1"
android:versionName="1.0">
<uses-feature
android:name="android.software.device_admin"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ToggleAdmin"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
<receiver android:name=".AlarmBroadCastReceiver"></receiver>
</application>
如果闹钟在设置后立即触发,则表明设置的时间已过去。在这种情况下,您的警报基于经过的实时时间,即自上次启动以来的时间。您传递 set()
方法的时间 - time * 60000
- 因此很可能是过去的时间。
要设置未来经过的实时警报,您需要将当前经过的时间添加到所需的时间间隔。例如:
alMgr.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + time * 60000, pendIntent);
我还要提到的是,由于 API 19 (KitKat),set()
方法不再准确。这可能不会对短间隔产生太大影响,但如果它很重要,您可以使用 setExact()
方法代替版本 >= 19。可以在 AlarmManager
的文档中找到更多信息。
我有一个名为 lock 的方法,它设置随机锁屏密码并在按下按钮时使用 DevicePolicyManager 锁定屏幕。就在 phone 锁定之前,此锁定方法还会安排警报在一定时间后响起。此警报调用一种方法将锁屏密码重置为存储值。
我遇到的问题是,每当按下调用我的锁定方法的按钮时,phone 就会像它应该的那样锁定,它还会像它应该的那样将锁屏密码重置为随机密码,所以在 phone 锁定后,用户可以尝试解锁它并弹出只接受随机密码的锁定屏幕。但是,如果用户在锁定屏幕上按回键,然后再次尝试解锁 phone,则锁定屏幕密码会立即设置为存储的 pin 值。如果用户再次锁定 phone 并尝试解锁它,也会发生这种情况。我希望在经过一定时间后而不是立即重置密码。
我已经在另一个 class 中配置了 DeviceAdmin 接收器。
我是否遗漏了 AlarmManager 中的某些内容或在我的锁定方法中做错了什么? 请注意,我是用这种方法更改实际设备的锁屏密码,并不是我自己制作锁屏。
按下我的按钮时调用的锁定方法
final Random rand=new Random();
public void lock(View v) {
int diceRoll;
setMins();
//this section schedules an alarm that calls my overridden broadcast receiver in this class
Intent alarmIntent=new Intent(this, AlarmBroadCastReceiver.class);
PendingIntent pendIntent=PendingIntent.getBroadcast(this, 1, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alMgr=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
alMgr.cancel(pendIntent);
alMgr.set(AlarmManager.ELAPSED_REALTIME, (time * 60000), pendIntent);
diceRoll=rand.nextInt(9999)+1;
if (mgr.isAdminActive(cn))
{
mgr.setPasswordQuality(cn, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
mgr.setPasswordMinimumLength(cn, 0);
//this sets the lock screen password to a random one
mgr.resetPassword(Integer.toString(diceRoll), 0);
mgr.lockNow();
}
else {
Intent intent =
new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, cn);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
getString(R.string.device_admin_explanation));
startActivity(intent);
}
}
这是我的 resetPasswordAgain 方法,从这个 class 覆盖的 BroadcastReceiver 调用。此方法将锁屏密码重置为存储值
public void resetPasswordAgain()
{
mgr.setPasswordQuality(cn, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
mgr.setPasswordMinimumLength(cn, 0);
mgr.resetPassword(SetPinDialogFragment.pin, 0);
}
来自此 class
的覆盖广播接收器 BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
resetPasswordAgain();
}
};
@Override
protected void onDestroy()
{
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
我在另一个 class 中也有一个基本的广播接收器,但是它被上面显示的覆盖了
public class AlarmBroadCastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
context.sendBroadcast(new Intent("CALL_METHOD"));
}
}
清单,以备不时之需
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fbtc141.test3">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
android:versionCode="1"
android:versionName="1.0">
<uses-feature
android:name="android.software.device_admin"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ToggleAdmin"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
<receiver android:name=".AlarmBroadCastReceiver"></receiver>
</application>
如果闹钟在设置后立即触发,则表明设置的时间已过去。在这种情况下,您的警报基于经过的实时时间,即自上次启动以来的时间。您传递 set()
方法的时间 - time * 60000
- 因此很可能是过去的时间。
要设置未来经过的实时警报,您需要将当前经过的时间添加到所需的时间间隔。例如:
alMgr.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + time * 60000, pendIntent);
我还要提到的是,由于 API 19 (KitKat),set()
方法不再准确。这可能不会对短间隔产生太大影响,但如果它很重要,您可以使用 setExact()
方法代替版本 >= 19。可以在 AlarmManager
的文档中找到更多信息。