Android xml 更改后构建变体的 Studio 过时 APK

Android Studio stale APK for build variant after xml changes

这是一个非常奇怪的问题。今天 AS (1.4) 停止在我的项目中正确地重新创建调试 apk:

我不太了解构建过程,所以我尝试的只是删除构建文件夹,重新导入项目和 Android Studio 上的旧重启/无效缓存。关于可能导致这种奇怪行为的原因或如何解决它的任何建议?

编辑: 很难确定这背后的行为 - 有时我注意到它始终只影响某些 xml 文件。看起来这个人有同样的问题:Android Studio project build issue

我花了几个小时从头开始重新安装 Android Studio,但问题仍然存在..

Daniel,我自己也确实注意到了这个问题。似乎某些更改根本不会传播,除非 ADB 检测到该应用程序当前未安装在目标设备上。

免责声明:这是一种解决方法,而不是对行为的解释,但它对我有用。为了解决这个问题,我配置了 运行 配置以在再次安装之前卸载有问题的包。请注意,卸载 APK 显然会影响数据库、首选项中的持久数据等,因此如果您的开发过程依赖于这些,请不要使用它。

步骤:(来自 here

  1. 在 Android Studio 中,单击 运行 按钮左侧的下拉列表,然后 select 编辑配置...
  2. 单击 Android 应用程序下的应用程序,然后在常规选项卡中找到标题 'Before Launch'
  3. 单击+按钮,select 运行外部工具,单击弹出窗口中的+按钮window。
  4. 提供一些名称(例如 adb uninstall)和描述,然后在 Program: 中键入 adb,在 Parameters: 中键入 uninstall <your-package-name>。 当您在弹出 window.
  5. 中单击“确定”时,请确保 select 编辑了新项目

注意:如果您的 PATH 环境变量中没有 adb,请在 Program: 字段中提供 adb 的完整路径(例如 /home/user/android/sdk/platform-tools/adb)。

再次抱歉,这不是对问题本身的解释,但这确实为我解决了问题。

告诉我它是如何为你工作的。

我实际上在不久前就发现了这个问题,而且它非常微妙。我的项目具有带有主源集的构建变体以及每个变体的源集。它的定义有点像这样:

sourceSets {

    def defaultDirectory = "src/main/"
    def flavorADirectory = "src/flavor_a/"

    flavor_a {
        java.srcDirs = [defaultDirectory + 'java', flavorADirectory + 'java']
        res.srcDirs = [defaultDirectory + 'res', flavorADirectory + 'res']
        manifest.srcFile flavorADirectory + 'AndroidManifest.xml'
    }

    def flavorBDirectory = "src/flavor_b/"

    flavor_b{
        java.srcDirs = [defaultDirectory + 'java', flavorBDirectory + 'java']
        res.srcDirs = [defaultDirectory + 'gift', flavorBDirectory + 'res']
        manifest.srcFile flavorBDirectory + 'AndroidManifest.xml'
    }
}

因此变体编译得很好,但每个 xml 更改都会触发完全重建。我不确定其背后的确切原因,但我相信 main sourceset 必须指定为一个单独的实体。 Android Studio 必须看到 main 关键字并更好地了解如何处理它。这意味着不需要指定默认目录 作为构建变体源集的一部分 像这样删除它,使问题消失并且不再发生持续重建:

 sourceSets {

    def defaultDirectory = "src/main/"

    main {
        java.srcDirs = [defaultDirectory + 'java']
        res.srcDirs = [defaultDirectory + 'res']
    }

    def flavorADirectory = "src/flavor_a/"

    flavor_a {
        java.srcDirs = [flavorADirectory + 'java']
        res.srcDirs = [flavorADirectory + 'res']
        manifest.srcFile flavorADirectory + 'AndroidManifest.xml'
    }

    def flavorBDirectory = "src/flavor_b/"

    flavor_b{
        java.srcDirs = [flavorBDirectory + 'java']
        res.srcDirs = [flavorBDirectory + 'res']
        manifest.srcFile flavorBDirectory + 'AndroidManifest.xml'
    }
}