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

如何将Expo安卓应用转为无障碍服务?构建开发版遇报错

问题背景

我接触Expo仅几周,想要开发一款安卓应用拦截器(App Blocker),比如限制每日打开YouTube不超过1小时,这类应用属于Android Accessibility Service。我了解需使用开发构建版本(Expo Go无法作为无障碍服务),因此通过npx create-expo-module@latest --local创建本地自定义模块(否则会触发GitHub上的相关报错)。随后我参照Android官方指南修改了模块中modules/my-module/android/src/main/AndroidManifest.xml文件,并创建了继承AccessibilityService的类:

import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo

class MyAccessibilityService : AccessibilityService() {

    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        if (event.packageName != null && event.packageName.toString() == "com.google.android.youtube") {
            performGlobalAction(GLOBAL_ACTION_BACK)
        }
    }

    override fun onInterrupt() { }
}

但运行eas build --profile development --platform android构建时,在“Run gradlew”步骤出现错误:

FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> Manifest merger failed with multiple errors, see logs
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 4m 3s
Error: Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.

请问我的实现方式是否正确?若正确,该如何解决此构建错误?


解答

一、实现方式的合理性

整体思路没问题:

  • 无障碍服务确实不能用Expo Go,必须用开发构建包,这个判断正确
  • 用本地自定义模块创建的方式避开远程模块的GitHub报错,操作正确
  • AccessibilityService的基础代码结构符合要求,重写了两个必要方法,当前逻辑能检测到YouTube并执行返回操作

但要注意:当前代码只是简单拦截打开,还没实现「每日不超过1小时」的计时逻辑,后续得补充本地存储(比如用Expo Secure Store或者安卓SharedPreferences)记录使用时长,结合时间戳判断是否超限。

二、修复Manifest合并错误

Manifest合并失败的核心是无障碍服务的配置不符合Expo模块规范,或者和主应用Manifest冲突,按以下步骤处理:

  1. 修正模块Manifest的服务声明
    打开modules/my-module/android/src/main/AndroidManifest.xml,确保无障碍服务的声明包含以下内容:

    • 必须加android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"权限
    • 必须用<intent-filter>指定android.accessibilityservice.AccessibilityService动作
    • 必须通过<meta-data>关联无障碍服务的配置文件
      正确示例:
    <service
        android:name=".MyAccessibilityService"
        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>
    
  2. 添加无障碍服务配置文件
    在模块的android/src/main/res/xml目录下新建accessibility_service_config.xml(xml目录不存在就手动创建),内容至少包含基础监听配置:

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeWindowStateChanged"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:accessibilityFlags="flagDefault"
        android:canPerformGestures="true" />
    

    其中typeWindowStateChanged是检测应用切换必须的事件类型,正好匹配你的拦截需求。

  3. 排查具体冲突项
    如果上述两步做完仍报错,直接执行eas build --profile development --platform android --debug查看详细合并日志,找到具体冲突点(比如权限重复、服务名冲突等)。常见冲突是主应用和模块Manifest重复声明权限,此时可在模块Manifest的冲突项上添加tools:replace属性(需先在根节点添加xmlns:tools="http://schemas.android.com/tools")。

  4. 验证模块配置文件
    检查modules/my-module/package.json中的android字段,确保正确声明了服务:

    "android": {
      "package": "com.yourname.mymodule",
      "services": [
        ".MyAccessibilityService"
      ]
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:53:26