【问题标题】:Method involving AlarmManager isn't functioning the way I need it to涉及 AlarmManager 的方法没有按我需要的方式运行
【发布时间】:2016-08-05 09:23:55
【问题描述】:

我有一个名为 lock 的方法,它设置一个随机的锁屏密码,并在按下按钮时使用 DevicePolicyManager 锁定屏幕。就在手机锁定之前,这种锁定方法还会安排闹钟在一定时间后响起。此警报调用一种将锁屏密码重置为存储值的方法。

我遇到的问题是,每当按下调用我的锁定方法的按钮时,手机就会按原样锁定,并且它还会将锁屏密码重置为应有的随机密码,以便在手机锁定后用户可以尝试解锁,然后会弹出只接受随机密码的锁屏。但是,如果用户在锁定屏幕上按回,然后再次尝试解锁手机,则锁定屏幕密码会立即设置为存储的 pin 值。如果用户再次锁定手机并尝试解锁,也会发生这种情况。我希望在经过一定时间后重设密码,而不是马上重设。

我已经在另一个类中配置了一个 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);
    }
}

这是我从此类中重写的 BroadcastReceiver 调用的 resetPasswordAgain 方法。此方法将锁屏密码重置为存储值

public void resetPasswordAgain()
{
    mgr.setPasswordQuality(cn,  DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
    mgr.setPasswordMinimumLength(cn, 0);

    mgr.resetPassword(SetPinDialogFragment.pin, 0);
}

这个类的覆盖广播接收器

 BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent) {
        resetPasswordAgain();
    }
};
    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        unregisterReceiver(broadcastReceiver);
    }

我在另一个类中也有一个基本的广播接收器,但是它被上面显示的那个覆盖了

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>

【问题讨论】:

  • 我不太确定我是否完全按照您的程序流程,但是您的警报基于经过的实时,因此如果设备的开启时间超过time * 60000 毫秒,警报将立即开火,就像过去一样。你可能想要SystemClock.elapsedRealtime() + time * 60000
  • 非常感谢您花时间浏览我的所有代码。你说的对。这现在完全按照我想要的方式工作。请将此作为答案发布,以便如果您愿意,我可以接受。我真的很感激。

标签: java android broadcastreceiver alarmmanager device-admin


【解决方案1】:

当警报在设置后立即触发时,这很好地表明设置的时间已经过去。在这种情况下,您的警报基于经过的实时时间,即自上次启动以来的时间。因此,您在 set() 方法中传递的时间 - time * 60000 - 很可能已经过去了。

要设置未来经过的实时警报,您需要将当前经过的时间添加到所需的时间间隔。例如:

alMgr.set(AlarmManager.ELAPSED_REALTIME,
    SystemClock.elapsedRealtime() + time * 60000, pendIntent);

我还要提到,由于 API 19 (KitKat),set() 方法不再精确。这可能不会在短时间内产生太大影响,但如果重要,您可以使用 setExact() 方法代替 >= 19 的版本。更多信息可以在AlarmManager 的文档中找到。

【讨论】:

  • 感谢您提供的信息,对不起,我无法投票,我没有足够的声誉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多