hello i'm trying to read json file located at resources folder in androidTest. I'm able to access json file located at resources folder in Test/resources but not in androidTest/resources.
I use following to get the json file in the Test/resources folder.
private fun getJson(path: String): String {
val uri = this.javaClass.classLoader?.getResource(path)
val file = File(uri?.path ?: "")
return String(file.readBytes())
}
Is there a way i can access the file under androidTest/resources ?
private fun getJson(fileName: Int): String {
val inputStream = InstrumentationRegistry.getInstrumentation().targetContext.resources.openRawResource(fileName)
val s = Scanner(inputStream).useDelimiter("\\A")
return if (s.hasNext()) s.next() else ""
}
Related
I have a resources folder where I added some images that I am using for unit testing. I am able to locate the path of the resources folder via InputStream. However, I need to access these images somehow and get their metadata. Is there a way I can run a filter loop inside the resources folder to get all images?
fun readImagesMetadata(inputStream: InputStream): Array<ImageMetadata>{
println("Reading images")
try {
val builder = StringBuilder()
val reader = BufferedReader(InputStreamReader(inputStream))
var str: String? = reader.readLine()
while (str != null) {
builder.append(str)
str = reader.readLine()
print(str)
}
return emptyArray()
} finally {
inputStream.close()
}
}
How to read data from JSON file on the resources directory?
I need to read a json file on the resources directory, convert it to a data class ("User")
I'm trying to adapt the following code
private fun getJSONFromAssets(): String? {
var json: String? = null
val charset: Charset = Charsets.UTF_8
try {
val myUsersJsonFile = assets.open("users.json")
val size = myUsersJsonFile.available()
val buffer = ByteArray(size)
myUsersJsonFile.read(buffer)
myUsersJsonFile.close()
json = String(buffer, charset)
} catch (ex: IOException) {
ex.printStackTrace()
return null
}
return json
}
but assets.open("users.json") is not recognized.
How is the best approach to read JSON files on the resources directory (mock data)?
You just need a minor change in your function...
private fun getJSONFromAssets(context: Context): String? {
...
val myUsersJsonFile = context.assets.open("users.json")
...
}
Assuming that your json file is at src/main/assets.
If you need to read a JSON file from the src/main/res/raw folder. You can use:
private fun getJSONFromAssets(context: Context): String? {
...
val myUsersJsonFile = context.resources.openRawResource(R.raw.users)
...
}
As you can see, you need a Context, so you can call from your activity.
getJSONFromAssets(this) // "this" is your activity (or another Context)
My app has an extract button that takes the data from text view and paste it in a text file "Ledger.txt". It creates a folder in Mobile internal Storage Root Directory "WaterLedger" and place a Ledger.txt file in it and if the text file is already present it appends the text in the file. The code is only working till android 9 not above.
In Android 10 on pressing Extract button it asks "grant permission to write file in storage" but even if you press Yes it still wont create folder (WaterLerger) and paste/update data in Text File (Ledger.txt)
Here is the code
class WriteFile: AsyncTask<String, Int, String>() {
private val mFolder = "/WaterLedger"
lateinit var folder: File
internal var writeThis = "string to cacheApp.txt"
internal var cacheApptxt = "Ledger.txt"
override fun doInBackground(vararg writethis: String): String? {
val received = writethis[0]
if(received.isNotEmpty()){
writeThis = received
}
folder = File(Environment.getExternalStorageDirectory(),"$mFolder/")
if(!folder.exists() || folder.exists()){
folder.mkdir()
val readME = File(folder, cacheApptxt)
val file = File(readME.path)
val out: BufferedWriter
try {
out = BufferedWriter(FileWriter(file, true), 1024)
out.write("****Ledger Updated On Dated:$currentDate*****\n")
out.newLine()
out.write(writeThis)
out.newLine()
out.close()
Log.d("Output_Success", folder.path)
} catch (e: Exception) {
Log.d("Output_Exception", "$e")
}
}
return folder.path
}
// Driver Code
extract.setOnClickListener {
var pathToFileCreated = ""
val anRW = ReadandWrite().readAndwriteStorage(this, this)
if (anRW) {
pathToFileCreated = WriteFile().execute("$StringBuilder").get()
Log.d("pathToFileCreated", pathToFileCreated)
Toast.makeText(this,"File Saved",android.widget.Toast.LENGTH_LONG).show()
}
This will give you External Pictures directory URI (You can create your desirable directory into it):
private fun createTextURI(): Uri? {
val imageCollection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
else
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val fileName = System.currentTimeMillis()
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "$fileName.txt")
put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
}
val finalURI = contentResolver.insert(imageCollection, contentValues)
resultUri = finalURI
return finalURI
}
Use this URI for file creation like this:
new File(finalURI.getPath());
And write into this file which you created above. ✌
Make sure you have WRITE_EXTERNAL_STORAGE permission.
Ref. Demo App
I am saving a file inside the Downloads directory of the device (Android 11) to be viewed later by my app. I'm allowing multiple file types like pdf, word etc. I was able to save the file like this: (I got this code sample from here)
#TargetApi(29)
private suspend fun downloadQ(
url: String,
filename: String,
mimeType: String
) =
withContext(Dispatchers.IO) {
val response = ok.newCall(Request.Builder().url(url).build()).execute()
if (response.isSuccessful) {
val values = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, filename)
put(MediaStore.Downloads.MIME_TYPE, mimeType)
put(MediaStore.Downloads.IS_PENDING, 1)
}
val resolver = context.contentResolver
val uri =
resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
uri?.let {
resolver.openOutputStream(uri)?.use { outputStream ->
val sink = outputStream.sink().buffer()
response.body()?.source()?.let { sink.writeAll(it) }
sink.close()
}
values.clear()
values.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(uri, values, null, null)
} ?: throw RuntimeException("MediaStore failed for some reason")
} else {
throw RuntimeException("OkHttp failed for some reason")
}
}
But when I tried to retrieve the file, I tried with the following ways that did not work:
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)
val id = cursor.getLong(idColumn)
Log.d("uri id ","$id")
val contentUri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI,id)
This approach threw an exception:
java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78
I got this ID (here 78) from the query and cursor from ContentResolver.query() and I hoped it to return the Uri from which I could get the File.
The second approach was this:
val uri = MediaStore.Downloads.getContentUri("external",id)
uri.path?.let { filePath ->
Log.d("uri path ",filePath)
val file = File(filePath)
} ?: Log.d("uri path ","null")
I used external as the directory based on this answer, but this approach also threw the same exception
java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78
At the end what ended up working was hardcoding something like this after I used a file explorer app to view the exact directory path:
val file = File("storage/emulated/0/Download/$name.$extension")
So my question is, how do I get the value of this path dynamically, and is this path the same for all devices that can be used like this way?
EDIT: I also wanted to know if I am using the filename and it's extension to view the file, then if user downloads another file with same name then how do I make sure that correct file is opened? (even if i make a separate directory for my app inside Download, user could still download the same file twice that has a name like storage/emulated/0/Download/myDir/file(2).extension )
Try with the following code it will help you.
private fun readFile(){
val FILENAME = "user_details.txt"
val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.toString() + "/" + "folderName"
)
} else {
File(
Environment.getExternalStorageDirectory()
.toString() + "/${Environment.DIRECTORY_DOWNLOADS}/" + "folderName"
)
}
dir.apply {
if(this.exists()) File(this, FILENAME).apply {
FileInputStream(this).apply {
val stringBuffer = StringBuffer()
var i: Int
while (this.read().also { i = it } != -1) {
stringBuffer.append(i.toChar())
}
close()
}
}
}
}
You can use
{Environment.DIRECTORY_DOWNLOADS} + "/folderName/file_name.mime_type"
/storage/emulated/0/Download/12d82c65-00a5-4c0a-85bc-238c28005c33.bin
I am new in using gson. I have tried several times to insert a Json Object inside a Json Array in Kotlin. I was able to successfully create the Json Array with Json Object and save it to internal storage. However, I wasn't able to insert Json Object inside it with this code. Any suggestions on how I would be able to achieve this? I've tried to get the file from internal storage and I couldn't fromJson it so I'm not sure if this idea would work. The data in the array are all strings. Here is my code:
fun save(){
var gson = Gson()
val filename = "name"
val file = context?.getFileStreamPath(filename)
if(file == null || !file.exists()){
val array= ArrayList<arraylist>()
array.add(arraylist("1","2","3"))
var json:String=gson.toJson(array).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}
}
else{
val file = File(context?.filesDir, filename)
val contents = file.readText()
val gson = GsonBuilder().create()
val content = gson.fromJson(contents, arraylist::class.java)
content.add(arraylist("1","2","3"))
var json:String=gson.toJson(content).replace("\\n", "\n")
}
}
I finally fixed this by reading it then saving it to internal storage. This is inside the else{} statement:
val file1 = File(context?.filesDir, filename)
val contents = file1.readText()
val array = gson.fromJson(contents, Array<arraylist>::class.java)
val arrayList = ArrayList(array.toMutableList())
arrayList.add(devices("Finally","Works","Wow"))
val json: String = gson.toJson(arrayList).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}