5

I have the following project structure

MyProject
|-- build.gradle
|-- client.private
|-- server.public
|-- app
|   |-- build.gradle
|   |-- lint.xml
|   |-- proguard-project.txt
|   |-- project.properties
|   `-- src

and would like to include client.private and server.public files into the assets folder of the final apk but unfortunately not able to do so.

Have the following in my app/build.gradle

...
android {
    ...
    applicationVariants.all { variant ->
        variant.mergeAssets.doLast {
            copy {
              from(['../client.private', '../server.public'])
              into("${buildDir}/assets/${variant.dirName}")
            }
        }
    }
}

but it only copies the files to app/build/assets/debug, its not packaged with the apk.

Krishnaraj
  • 2,360
  • 1
  • 32
  • 55
  • If your packaging the file into the `apk` then you can no longer consider it private. Extracting a raw file from an `apk` is as trivial as renaming it to a `.zip` and decompressing the archive. – JBirdVegas Jan 04 '16 at 18:22
  • Yes, true. They are actually keystores containing private and public keys for a ssl socket connection. Unfortunately, I don't know a better way. – Krishnaraj Jan 04 '16 at 18:32
  • Get them from a server. Have the client send some kind of authentication to the server then give the key back to the client then. Packaging it is security issue as now everyone has your private keys. – JBirdVegas Jan 04 '16 at 18:44
  • But still the initial key exchange would be insecure right? Maybe I should post a new question on security.stackexchange.com ☺ – Krishnaraj Jan 04 '16 at 19:25

2 Answers2

9

EDITED

Please try to use sourceSets. (Path edited)

android {
  sourceSets {
    main {
        assets.srcDirs = ['../client.private','../server.public']
    }
  }
}

You can check path each assets directories.

afterEvaluate {
    android.sourceSets.main.assets.srcDirs.each{println it}
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
takahirom
  • 1,934
  • 2
  • 12
  • 21
4

UPDATE (correct solution)

Finally! think I have understood what the comment meant

android {
  ...
  ...
  applicationVariants.all { variant ->
    variant.mergeResources.doLast {
      copy {
        from (["../client.private", "../server.public"])
        into ("$outputDir/raw")
      }
    }
  }
}

Older solution (works but not an ideal one)

I haven't been able to find a way to include individual files in the sourceSets so the next trick was to try copying the files to the raw folder

The solution is based on this reddit thread

task copyKeyStores(type: Copy) {
    from files(["../client.private", "../server.public"])
    into 'src/main/res/raw'
}
tasks.copyKeyStores.execute()

Note: As per one of the comments in the reddit thread, there is a better way but I am unable to figure it out.

Community
  • 1
  • 1
Krishnaraj
  • 2,360
  • 1
  • 32
  • 55
  • 1
    `variant.mergeResources` throws "API 'variant.getMergeResources()' is obsolete and has been replaced with 'variant.getMergeResourcesProvider()'." Any solutions? – EmmanuelMess Dec 28 '19 at 16:13