【问题标题】:Exclude temporary Realm files from Gradle build从 Gradle 构建中排除临时 Realm 文件
【发布时间】:2018-11-27 00:02:28
【问题描述】:

Realm 提供了一个名为“Realm Studio”的数据库查看器,允许用户浏览其数据库的内容。当应用程序用于查看数据库时,它会在数据库的目录中创建几个“临时”文件,即:

  • .realm.lock 文件。
  • .realm.note 文件。
  • .realm.management 目录包含:
    • access_control.control.mx 文件。
    • access_control.new_commit.cv 文件。
    • access_control.pick_writer.cv 文件。
    • access_control.write.mx 文件。

在 Android 环境中,一个预先存在的 Realm 数据库有时会通过将数据库放置在 /assets 目录中而随应用程序一起提供。因此,当使用 Realm Studio 查看该数据库时,会在/assets 中生成上述文件。由于未知原因,这会导致 Gradle 在 :app:generateDebugAssets 任务之后无限期挂起,显然是在 :app:mergeDebugAssets 任务处。

因此,我想找到一种方法从构建中排除这些文件。我尝试了几种方法,例如:

applicationVariants.all { variant ->
    if (variant.buildType.name == 'debug') {
        variant.mergeAssets.doLast {
            delete(fileTree(dir: variant.mergeAssets.outputDir, includes: ['**/*.cv', '**/*.mx', '**/*.lock', '**/*.note']))
        }
    }
}

和其他方法,例如:

sourceSets.main.assets.exclude 'appData.realm.management'
sourceSets.main.assets.exclude 'appData.realm.management/access_control.control.mx'
sourceSets.main.assets.exclude 'appData.realm.management/access_control.new_commit.cv'
sourceSets.main.assets.exclude 'appData.realm.management/access_control.pick_writer.cv'
sourceSets.main.assets.exclude 'appData.realm.management/access_control.write.mx'
sourceSets.main.assets.exclude 'appData.realm.lock'
sourceSets.main.assets.exclude 'appData.realm.note'

无济于事。

如何在运行构建时指示 Gradle 排除这些文件?

编辑:来自./gradlew -d app:mergeDebugAssets的重复输出的小sn-p:

[org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
[org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 2572066816}
[org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 2572066816}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 308281344}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 2567909376}
[org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 2567909376}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 308281344}
[org.gradle.launcher.daemon.server.Daemon] DaemonExpirationPeriodicCheck running
[org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
[org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 2564087808}
[org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 2564087808}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 308281344}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 8589934592, Free: 2560860160}
[org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 8589934592, Free: 2560860160}
[org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 1431830528, Committed: 308281344}
[org.gradle.launcher.daemon.server.Daemon] DaemonExpirationPeriodicCheck running
[org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
[org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
...

【问题讨论】:

  • 以上解决方案都不起作用?任何错误信息?

标签: android gradle android-gradle-plugin realm build.gradle


【解决方案1】:

我认为问题在于您没有删除.realm.management目录。

android {

    ...

    applicationVariants.all { variant ->
        if (variant.buildType.name == 'debug') {
            variant.mergeAssets.doLast {
                delete(fileTree(dir: variant.mergeAssets.outputDir, includes: ['**/.realm.management', '**/*.lock', '**/*.note']))
            }
        }
    }
}

资产目录内容:

apk 中的资产目录内容:

【讨论】:

  • 这看起来几乎与已经与问题一起提出的方法相似。
  • @MartinZeitler:是的,你是对的。我已添加 '**/.realm.management' 以删除。
  • 基本问题可能是独占文件访问冲突。我可能是错的(关于 aapt 和资产),但会假设空目录通常不会被打包。
  • @aminography 我注意到您提供的屏幕截图中的.realm.management 目录没有以“appData”为前缀,即appData.realm.management/。这个解决方案对你有用吗?它似乎无法解决问题。
  • @aminography 几乎必须对此进行投票,因为它提供了资产目录的屏幕截图,这使我能够编写 cleanupRealm 任务。否则我不知道该写什么。
【解决方案2】:

猜你可能正在使用旧版本的 Realm Studio, 因为根据issue #842 和pull request #847 的说法,这些目录应该同时被适当地清理——如果没有的话,还应该报告——而不是停滞不前。当前版本 3.12 应该已修复(基本上是 6 月 18 日之后的任何版本)。如果这不应该有帮助,你能做的最好的就是在问题 #842 下报告它;或提交一个新的问题,即参考问题 #842。还要检查文件系统权限,允许运行 gradle 的用户在那里删除;手动将文件移开“可能”会有所帮助,因此当前用户可以重新创建它们,然后随后能够删除他自己的文件。

使用 gradle 的两种方法都是解决方法 - 因为它不应该首先发生。

为了获得“为​​什么停止”的更多信息,请在终端中运行以下命令:

./gradlew -d app:generateDebugAssets

分别在 Windows 上(问题既不指示操作系统也不指示 Realm Studio 版本):

gradlew.bat -d app:generateDebugAssets

编辑:甚至可以在每次构建之前删除这些文件:

task cleanupRealm(type: Delete) {
    delete project.projectDir.path + "/src/main/assets/.realm.management"
    delete project.projectDir.path + "/src/main/assets/appData.realm.lock"
    delete project.projectDir.path + "/src/main/assets/appData.realm.note"
}

tasks.whenTaskAdded { task ->
    if (task.name == "preDebugBuild" || task.name == "preReleaseBuild") {
        task.dependsOn cleanupRealm
    }
}

将任务图更改为:

:app:checkDebugClasspath
:app:cleanupRealm
:app:preBuild
:app:preDebugBuild

【讨论】:

  • 我认为链接的 PR 中显示的描述和代码与 Electron 的渲染器进程和包含 renderer- 模式的相关文件有关,因为它们似乎与此问题无关。我正在运行最新版本的 Realm Studio。您手动运行任务的建议很棒,因为app:generateDebugAssets 成功完成。 :app:generateDebugAssets UP-TO-DATE 是在 Android Studio 中构建时最后打印的内容,但真正的罪魁祸首似乎是 :app:mergeDebugAssets,它反复打印有关 daemon addresses registry 的日志。
  • @Orbit 什么时候运行./gradlew -d :app:mergeDebugAssets?它可能正在等待访问共享锁,但它没有获得...
  • 任务在 75% 处挂起。我将在原始帖子中添加一个小的 sn-p 输出,因为完整的输出非常大,所以该输出会被重复记录。请注意,./gradlew -s app:mergeDebugAssets 没有显示异常。另外,请注意,如果没有这些“临时”Realm 文件,此任务通常会在几秒钟内完成。
  • @Orbit 刚刚添加了造成这种情况的任务。它没有经过测试,因为我没有这些文件 - 但至少正确添加了任务,具有正确的类型,并且我相信只有路径可能会有所不同。然而,当使用独占锁打开这些文件中的任何一个时,它可能会失败。
  • 您的 cleanupRealm 任务效果很好,尽管我已将调用改为使用 delete project.projectDir.path。这会在每次 Gradle 同步和每次构建时删除这些临时文件。知道为什么会出现mergeDebugAssets 的问题吗?有没有办法让构建忽略这些文件而不是删除它们?
【解决方案3】:

试试看:

android {
    aaptOptions {
        ignoreAssetsPattern "!*.cv:!*.mx:!*.lock:!*.note" 
    }
}

来自aapt 二进制来自build-tools 文件夹:

./aapt
[...]
--ignore-assets
   Assets to be ignored. Default pattern is:
   !.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~

【讨论】:

  • aaptOptions 块应该放在哪里?我尝试的两个选项(在android {} 和android { buildTypes {} } 中的另一个选项)似乎都没有解决问题。
  • 是的,它在 android 块中。它根本不起作用?
  • ignoreAssetsPattern = ignoreAssetsPattern + "..." 将添加而不是替换。
  • @ToYonos 正确,它似乎无法解决问题。注意在设置ignoreAssetsPattern之前,ignoreAssets和ignoreAssetsPattern都是null。
猜你喜欢
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
  • 2015-04-26
  • 2014-07-23
相关资源
最近更新 更多