X量不活动后如何锁定用户?

时间:2018-04-11 15:02:28

标签: java android android-activity android-context

每次用户在X时间内处于非活动状态时,我都需要显示Activity。我正在尝试使用自定义CountDownTimer来实现这一目标,该onUserInteraction会在BaseActivity中启动@Override public void onUserInteraction() { super.onUserInteraction(); inactivityTimer.cancel(); inactivityTimer.start(); }

CountDownTimer

在我的自定义Activity中,我启动了所需的onFinish @Override public void onFinish() { BaseActivity baseActivity = new BaseActivity(); Log.i("TIMER ENDED: ", "NOW STARTING LOCKACTIVITY"); baseActivity.showLock(); }

showLock()

这是BaseActivity

中的public void showLock() { Intent intent = new Intent(getApplicationContext(), LockActivity.class); startActivity(intent); } 方法
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference

每次定时器结束时,我得到的是NPE。 (getApplication().getBaseContext())即使我尝试使用thisthis.getBaseContext()this.getApplicationContext()getApplicationContext()getBaseContext()getApplicationContext()代替Context

但是,如果我在方法调用中设置@Override public void onFinish() { BaseActivity baseActivity = new BaseActivity(); Context context = MyApplication.getInstance().getApplicationContext(); Log.i("TIMER ENDED: ", "NOW STARTING LOCKACTIVITY"); baseActivity.showLock(context); } ,如下所示:

showLock()

这是public void showLock(Context context) { Intent intent = new Intent(context, LockActivity.class); startActivity(intent); }

java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference

这次我得到另一个NPE(Context)。

所以我的问题是,每次从当前showLock()调用Activity时,如何调用该方法,我该如何获得正确的Activity

重要说明:我的项目中的每个BaseActivity都会继承AppCompatActivityBaseActivity会继承Handler

修改

我尝试了Marcin的建议,在处理了几个错误后,我最终使用了他的方法。如果其他人很好奇,想要知道如何在X不活动后打开一个活动,这对我有用:

由于我的所有活动都继承了一个主WeakReference,因此我在其中设置了一个自定义BaseActivity,其handleMessage代表private static class InactivityHandler extends Handler { private WeakReference<BaseActivity> baseActivityWeakReference; private InactivityHandler(BaseActivity baseActivity) { baseActivityWeakReference = new WeakReference<>(baseActivity); } @Override public void handleMessage(Message msg) { BaseActivity baseActivity = baseActivityWeakReference.get(); if (baseActivity != null) { baseActivity.showLock(); } } } 。我也覆盖onUserInteraction,我称之为我想要的方法:

Message

并在@Override public void onUserInteraction() { super.onUserInteraction(); inactivityHandler.removeMessages(MESSAGE_WHAT, MESSAGE_TOKEN); inactivityHandler.sendMessageDelayed(inactivityHandler.obtainMessage(MESSAGE_WHAT, MESSAGE_TOKEN), DELAY_TIME); } 中在一段时间后向队列发送showLock

public void showLock() {
    Intent intent = new Intent(this, LockActivity.class);
    startActivity(intent);
}

对于好奇,这是我的{{1}}方法:

{{1}}

3 个答案:

答案 0 :(得分:2)

根据您的描述我假设在用户处于非活动状态一段时间后,您的应用需要提供锁定屏幕,用户需要重新输入凭据。

除非整个场景涉及任何计数(例如,您显示实际倒计时),否则#[100 rows x 10 columns] mm_dates_base = pd.concat([df] * 100, ignore_index=True) In [41]: %%timeit ...: ...: for col in varlist2: ...: a = pd.to_datetime(mm_dates_base[col], errors='coerce', dayfirst=True) ...: b = pd.to_datetime(mm_dates_base[col], errors='coerce', format='%d%b%Y') ...: mm_dates_base[col] = a.combine_first(b) ...: 5.13 ms ± 46.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [43]: %%timeit ...: df1 = mm_dates_base[varlist2].apply(pd.to_datetime, errors='coerce', dayfirst=True) ...: df2 = mm_dates_base[varlist2].apply(pd.to_datetime, errors='coerce', format='%d%b%Y') ...: ...: mm_dates_base[varlist2] = df1.combine_first(df2) ...: 14.1 ms ± 92.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 可能不是执行此任务的最佳选择。

相反,您可以使用CountDownTimer。在Android中,主线程具有与之关联的消息队列。处理程序能够将消息发布到此队列,以便稍后在给定时间接收消息。

您的示例实现可能如下所示:

Handler

您可以使用处理程序发送Runnables或Messages。在我们的例子中,消息完全正常。因此,在您的基本活动中,您可能会有一些与消息相关的字段:

private static class LockScreenHandler extends Handler {
  private WeakReference<BaseActivity> activityRef;

  public LockScreenHandler(BaseActivity activity) {
    activityRef = new WeakReference<>(activity);
  }

  @Override public handleMessage(Message msg) {
    BaseActivity activity = activityRef.get();

    if (activity != null) {
      activity.showLock();
    } // Otherwise the activity got destroyed in the meantime
  }
}

然后在onUserInteraction中使用你的处理程序:

private static final int MESSAGE_WHAT = 1;
private static final Object MESSAGE_TOKEN = new Object();

如果您决定遵循CountDownTimer解决方案,您可以通过创建静态内部类并在构造函数中提供活动来遵循相同的技术。

无论你采用哪种方式,重要的是要注意,你的BaseActivity可以被系统破坏,并且Handler(以及内部依赖Handler的CountDownTimer)的不当使用可以防止对这个活动的引用被破坏并因此导致内存泄漏。因此:

  • 如果您使用Handler或CountDownTimer作为内部类,请确保它是@Override public void onUserInteraction() { super.onUserInteraction(); handler.removeMessages(MESSAGE_WHAT, MESSAGE_TOKEN); handler.postDelayed(handler.obtainMessage(MESSAGE_WHAT, MESSAGE_TOKEN), INACTIVITY_DELAY); } 。非静态内部类包含对其封闭类的引用。消息保存对其目标处理程序的引用,因此只要消息在队列中,它的处理程序就不会被销毁。

  • 使用WeakReference保存您的活动的原因与上述相同。如果没有其他内容包含对给定对象的引用,则清除WeakReferences。

答案 1 :(得分:1)

活动 是一个上下文本身。因此,只需在活动中使用this即可。

public void showLock() {
    Intent intent = new Intent(this, LockActivity.class);
    startActivity(intent);
}

答案 2 :(得分:0)

如果这不是一个选项,因为你要覆盖一个函数,你应该使用MainActivity.this(当MainActivity是你的活动名称时)

MainActivity.this.startActivity(MainActivity.this, ...);