日积月累系列之一:Android检测用户一段时间无操作
如果有一个需求,判断用户一段时间没有操作后,锁屏,应该怎么做?
使用dispatchTouchEvent?但实际不是所有情况都会调用这一个方法
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
可以使用 使用Window.setCallback
public void setCallback(Callback callback) {
mCallback = callback;
}
class TouchLiveData(val activity: Activity) : LiveData<Boolean>() {
private val logTag = "TouchLiveData"
private var job: Job? = null
init {
activity.window.callback = object : Window.Callback {
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
postValue(true)
return activity.dispatchKeyEvent(event)
}
override fun dispatchKeyShortcutEvent(event: KeyEvent?): Boolean {
postValue(true)
return activity.dispatchKeyShortcutEvent(event)
}
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
postValue(true)
return activity.dispatchTouchEvent(event)
}
override fun dispatchTrackballEvent(event: MotionEvent?): Boolean {
postValue(true)
return activity.dispatchTrackballEvent(event)
}
override fun dispatchGenericMotionEvent(event: MotionEvent?): Boolean {
postValue(true)
return activity.dispatchGenericMotionEvent(event)
}
override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent?): Boolean {
postValue(true)
return activity.dispatchPopulateAccessibilityEvent(event)
}
override fun onCreatePanelView(featureId: Int): View? {
postValue(true)
return activity.onCreatePanelView(featureId)
}
override fun onCreatePanelMenu(featureId: Int, menu: Menu): Boolean {
postValue(true)
return activity.onCreatePanelMenu(featureId, menu)
}
override fun onPreparePanel(featureId: Int, view: View?, menu: Menu): Boolean {
postValue(true)
return activity.onPreparePanel(featureId, view, menu)
}
override fun onMenuOpened(featureId: Int, menu: Menu): Boolean {
postValue(true)
return activity.onMenuOpened(featureId, menu)
}
override fun onMenuItemSelected(featureId: Int, item: MenuItem): Boolean {
postValue(true)
return activity.onMenuItemSelected(featureId, item)
}
override fun onWindowAttributesChanged(attrs: WindowManager.LayoutParams?) {
postValue(true)
return activity.onWindowAttributesChanged(attrs)
}
override fun onContentChanged() {
postValue(true)
return activity.onContentChanged()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
postValue(true)
return activity.onWindowFocusChanged(hasFocus)
}
override fun onAttachedToWindow() {
postValue(true)
return activity.onAttachedToWindow()
}
override fun onDetachedFromWindow() {
postValue(true)
activity.onDetachedFromWindow()
}
override fun onPanelClosed(featureId: Int, menu: Menu) {
postValue(true)
activity.onPanelClosed(featureId, menu)
}
override fun onSearchRequested(): Boolean {
postValue(true)
return activity.onSearchRequested()
}
override fun onSearchRequested(searchEvent: SearchEvent?): Boolean {
postValue(true)
return activity.onSearchRequested(searchEvent)
}
override fun onWindowStartingActionMode(callback: ActionMode.Callback?): ActionMode? {
postValue(true)
return activity.onWindowStartingActionMode(callback)
}
override fun onWindowStartingActionMode(callback: ActionMode.Callback?, type: Int): ActionMode? {
postValue(true)
return activity.onWindowStartingActionMode(callback, type)
}
override fun onActionModeStarted(mode: ActionMode?) {
postValue(true)
activity.onActionModeStarted(mode)
}
override fun onActionModeFinished(mode: ActionMode?) {
postValue(true)
activity.onActionModeFinished(mode)
}
}
}
override fun postValue(value: Boolean?) {
cancelAndRestartDelay()
// LogUtils.d(TouchLiveData::class.java.simpleName,"postValue :$value")
super.postValue(value)
}
private val serialPorDataReceivedListener = object : OnDataReceivedListener {
override fun invoke(p1: SerialportReceivedData) {
cancelAndRestartDelay()
postValue(true)
}
}
override fun onActive() {
LogUtils.d(logTag,"onActive")
cancelAndRestartDelay()
super.onActive()
}
override fun onInactive() {
LogUtils.d(logTag,"onInactive")
stopDelay()
super.onInactive()
}
private fun cancelAndRestartDelay() {
job?.cancel()
job = mainScope.launch {
// delay(2 * 60 * 1000)
delay(10 * 1000)
postValue(false)
}
}
private fun stopDelay() {
job?.cancel()
}
}
在Activity里使用
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
TouchLiveData(this@MainActivity).asFlow().collectLatest {
.....
}
}
}
}
}
}