Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android+Gradle: list directories into a file

Tags:

android

gradle

I'm trying to convert a task I have in an ANT build to Gradle:

<target name="index-assets" depends="copy-assets">
    <path id="assets.path">
        <!-- contexts (and surplus) -->
        <dirset id="assets.dirset" dir="assets/" defaultexcludes="yes"/>
        <!-- assets -->
        <fileset id="assets.fileset" dir="assets/" includes="**" excludes="asset.index" defaultexcludes="yes"/>
    </path>

    <pathconvert pathsep="${line.separator}" property="assets" refid="assets.path" dirsep="/">
        <mapper>
            <globmapper from="${basedir}/assets/*" to="*" handledirsep="yes"/>
        </mapper>
    </pathconvert>

    <echo file="assets/asset.index">${assets}</echo>

</target>

<target name="-pre-build" depends="index-assets"/>

I guess I'm still not completely grasping basic Gradle concepts, but here's what I tried:

task indexAssets << {

def assets = file("assets")
def contexts = files(assets)
inputs.file(assets)
outputs.file("assets/assets-gradle.index")

def tree = fileTree(dir: 'assets', include: ['**/*'], exclude: ['**/.svn/**', 'asset.index'])

contexts.collect { relativePath(it) }.sort().each { println it }
tree.collect { relativePath(it) }.sort().each { println it }
}
  1. The tree is fine, but contains only file (leaf) paths
  2. I just can't seem to get the simple clean list of directories (contexts) though. I tried several other variants (tree, include/exclude), but I either get a single file in that directory, the directory name itself or nothing. I just want a simple list of directories found in the 'assets' dir.
  3. For now I'm just trying to print the paths, but I'd also like to know the proper way to later write these into a file (like ANT's echo file).

    Update:
    This groovy snippet seems to do that part (+ svn filter), but I'd rather find a more "Gradley" way of doing this task. It runs in a context of a build variant later as a pre-build dependency. (NOTE: I had to specify the 'Project' as part of the path in this hack since I guess I'm not in that project context for the task?)

    def list = []
    def dir = new File("Project/assets")
    dir.eachDirMatch (~/^(?!\.svn).*/) { file ->
        list << file
    }
    
    list.each {
        println it.name
    }
    
like image 393
snowdragon Avatar asked Sep 02 '13 09:09

snowdragon


1 Answers

Ok, This is the cleanest way I found so far.

I'd still be happier if FileTree collect patterns were able to do this, but this is almost as concise, and maybe even slightly more explicit and self-explanatory.

The key is using fileTree.visit with relativePath (see below)
As an extra, I've added the task context and adding dependency on the relevant build step, as well as writing the actual assets index file per variant build.

Why is this required, you ask? Since AssetManager is very slow, see here and the answer thread that follows (which triggered the original ANT target).

android {

task indexAssets {
    description 'Index Build Variant assets for faster lookup by AssetManager later'

    ext.assetsSrcDir = file( "${projectDir}/src/main/assets" )        
    ext.assetsBuildDir = file( "${buildDir}/assets" )

    inputs.dir assetsSrcDir
    //outputs.dir assetsBuildDir

    doLast {
        android.applicationVariants.each { target ->
            ext.variantPath = "${buildDir.name}/assets/${target.dirName}"
            println "copyAssetRec:${target.dirName} -> ${ext.variantPath}"

            def relativeVariantAssetPath = projectDir.name.toString() + "/" + ext.variantPath.toString()
            def assetIndexFile = new File(relativeVariantAssetPath +"/assets.index")
            def contents = ""

            def tree = fileTree(dir: "${ext.variantPath}", exclude: ['**/.svn/**', '*.index'])

            tree.visit { fileDetails ->
                contents += "${fileDetails.relativePath}" + "\n"
            }

            assetIndexFile.write contents
        }
    }
}

indexAssets.dependsOn {
    tasks.matching { task -> task.name.startsWith( 'merge' ) && task.name.endsWith( 'Assets' ) }
}

tasks.withType( Compile ) {
    compileTask -> compileTask.dependsOn indexAssets
}

    ...
}
like image 102
snowdragon Avatar answered Sep 29 '22 07:09

snowdragon