日积月累系列之一:Android检测用户一段时间无操作

305 阅读1分钟

日积月累系列之一: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 {
                        .....
                    }
                }
            }
        }
    }
}