You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平台.NET MAUI应用:检测用户停止使用设备的方案问询

Android全局无交互检测与应用启动方案

核心思路

要实现后台监听全局触摸交互并在用户x分钟无操作时启动应用显示图片,Android系统下唯一合法的方式是借助AccessibilityService(无障碍服务)记录用户最后操作时间,结合定时任务检查无交互时长,最终触发应用启动。

步骤1:实现无障碍服务监听触摸事件

无障碍服务可全局监听系统交互事件,我们用它来追踪用户的最后操作时刻:

1.1 创建AccessibilityService子类

class TouchMonitorService : AccessibilityService() {
    companion object {
        // 静态变量存储最后交互时间,供定时任务读取
        var lastInteractionTime = System.currentTimeMillis()
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        event?.let {
            // 监听触摸、点击、长按等交互事件,更新最后操作时间
            when (it.eventType) {
                AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
                AccessibilityEvent.TYPE_VIEW_CLICKED,
                AccessibilityEvent.TYPE_VIEW_LONG_CLICKED -> {
                    lastInteractionTime = System.currentTimeMillis()
                }
            }
        }
    }

    override fun onInterrupt() {
        // 服务被中断时的默认处理,无需额外操作
    }
}

1.2 注册服务并配置权限

在AndroidManifest.xml中注册服务,声明无障碍权限:

<service
    android:name=".TouchMonitorService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config" />
</service>

1.3 创建无障碍服务配置文件

在res/xml目录下新建accessibility_service_config.xml,指定监听的事件类型:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeTouchInteractionStart|typeViewClicked|typeViewLongClicked"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="false"
    android:description="@string/accessibility_service_description" />

同时在strings.xml中添加服务描述:

<string name="accessibility_service_description">监听设备交互,在无操作时展示图片</string>

步骤2:定时检查无交互时长并启动应用

使用WorkManager实现周期性检查,平衡功能需求与后台耗电:

2.1 实现Worker子类

class InactivityCheckWorker(
    context: Context,
    workerParams: WorkerParameters
) : Worker(context, workerParams) {

    override fun doWork(): Result {
        // 从参数中获取无操作阈值(分钟)
        val thresholdMinutes = inputData.getLong("THRESHOLD_MINUTES", 5)
        val inactivityThreshold = thresholdMinutes * 60 * 1000

        val currentTime = System.currentTimeMillis()
        // 判断是否超过无操作时长
        if (currentTime - TouchMonitorService.lastInteractionTime >= inactivityThreshold) {
            // 启动图片展示Activity
            val intent = Intent(applicationContext, ImageDisplayActivity::class.java)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            applicationContext.startActivity(intent)
        }
        // 任务执行成功,继续周期性调度
        return Result.success()
    }

    companion object {
        // 启动周期性检查任务
        fun startPeriodicCheck(context: Context, thresholdMinutes: Long) {
            val constraints = Constraints.Builder()
                .setRequiredNetworkType(NetworkType.NOT_REQUIRED)
                .build()

            val data = Data.Builder()
                .putLong("THRESHOLD_MINUTES", thresholdMinutes)
                .build()

            // 每15分钟检查一次,可根据需求调整间隔
            val request = PeriodicWorkRequestBuilder<InactivityCheckWorker>(15, TimeUnit.MINUTES)
                .setConstraints(constraints)
                .setInputData(data)
                .build()

            WorkManager.getInstance(context).enqueue(request)
        }
    }
}

步骤3:实现图片展示Activity

创建全屏Activity,显示目标图片,并在用户触摸时关闭:

3.1 Activity代码

class ImageDisplayActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 设置全屏模式
        window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN
        )
        supportActionBar?.hide()
        setContentView(R.layout.activity_image_display)

        // 加载并显示图片
        val imageView = findViewById<ImageView>(R.id.display_image)
        imageView.setImageResource(R.drawable.your_target_image) // 替换为你的图片资源

        // 触摸屏幕时关闭Activity,回到之前的应用
        imageView.setOnTouchListener { _, _ ->
            finish()
            true
        }
    }
}

3.2 布局文件(activity_image_display.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/display_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

</RelativeLayout>

关键注意事项

  1. 无障碍服务授权:应用首次启动时,需要引导用户手动开启无障碍服务,可通过以下代码跳转到设置页面:
    fun openAccessibilitySettings(context: Context) {
        val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }
    
  2. Android 12+后台启动限制:通过无障碍服务上下文启动Activity不受后台启动限制,若用普通WorkManager启动可能被拦截,建议优先通过无障碍服务触发启动逻辑。
  3. 耗电优化:避免设置过短的检查间隔,推荐10-15分钟一次,减少后台唤醒次数。

内容的提问来源于stack exchange,提问作者lamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:43:20