Search code examples
androidmulti-module

Where to place datafiles in a multimodule project


I have a multimodule project with the following structure:

app:
core:
|- common
feature:
|-games:
| |-general:
| |-meaninggame:
|
|-settings

etc.

The game needs a list of proverbs whcihb ultimately will be downloaded from a backend but for testing purposes will be read from a file. In the module :general I have a class ProverbRepositoryFileImpl:

class ProverbRepositoryFileImpl: ProverbRepository {

override fun getListOfProverbs(number: Int): List<Proverb> {
    val proverbList =  proverbs()
    return if(number == 0 || proverbList.size<number){
        proverbList
    }
    else{
        val start = (0 .. proverbList.size-number).random()
        proverbList.subList(start,start+number)
    }
}

override fun getListOfProverbsContaining(key: String, number: Int): List<Proverb> {
    val proverbList =  proverbs().filter{it.part_1.contains(key) || it.part_2.contains(key)}
    return if(number == 0 || proverbList.size<number){
        proverbList
    }
    else{
        val start = (0 .. proverbList.size-number).random()
        proverbList.subList(start,start+number)
    }
}

//Helper function to read json from file
private fun proverbs(): List<Proverb> {
    val serverResponse = getJsonResponse("proverbs.json")
    val proverbList = Json.decodeFromString<Array<Proverb>>(serverResponse)
    return proverbList.toList()
}

private fun getJsonResponse(filepath:String):String{
    val uri = javaClass.classLoader?.getResource(filepath)
    val file = uri?.path?.let { File(it) }
    file?.let{return String(file.readBytes())}?:let{return ""}
}

}

The last two functions read a list of json formatted proverbs from a file. The file is placed in the resources directory of the general module. When I run the tests all test passes, so the file is being read. But when I run the app to play the game, a java.io.FileNotFoundException is being thrown.

Where do I have to place the file to have the proverbs read? Or should I use another approach to get the list of proverbs into the game?


Solution

  • I solved the problem by using the following code:

    class LoadJsonFromFile(private val context:Context ){
        fun loadFile(resourceId:Int): String {
            var json: String? = null
            try {
                val inputStream = context.resources.openRawResource(resourceId)
                val size = inputStream.available()
                val buffer = ByteArray(size)
                inputStream.read(buffer)
                inputStream.close()
                json = String(buffer, StandardCharsets.UTF_8)
            } catch (e: IOException) {
                e.printStackTrace()
            }
            return json?:""
        }
    }
    

    The class is injected in the ProverbRepositoryFileImpl class and the helper function is changed as shown below:

    class ProverbRepositoryFileImpl(val fileLoader:LoadJsonFromFile): ProverbRepository{
    
    ...
    
    //Helper function to read json from file
        private fun proverbs(): List<Proverb> {
            val serverResponse = fileLoader.loadFile(R.raw.proverbs)
            val proverbList = Json.decodeFromString<Array<Proverb>>(serverResponse)
            return proverbList.toList()
        }
    }