I’ve an app that is have 3 GlobalScope
s:
- First reading a stream from url, and return
InputStream
- Second, start after the completion of the first one, save the
InputStream
in the device, and return the saved fileuri
- Third, start after the completion of the second one, and do some processing with the file
I’ve something wrong in the second scope, as the file is not saved, my full code is below:
MainActivity
package com.example.dl
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.example.dl.databinding.ActivityMainBinding
import kotlinx.coroutines.*
import java.io.File
import java.io.InputStream
import java.net.URL
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
// setContentView(R.layout.activity_main)
val context = this
val urlFile:URL = URL( "https://drive.google.com/uc?export=download&id="+
"1kRtYw3_Yd7he0HjbgNlAAl9we9tQEGvm")
// show image url in text view
binding.tvDownload.text = urlFile.toString()
val tag = "Main Activity"
Log.i(tag, "Trying t get stream")
binding.button.setOnClickListener {
it.isEnabled = false // disable button
binding.progressBar.visibility = View.VISIBLE
// GlobalScope 1
// async task to get / download bitmap from url
val result: Deferred<InputStream?> = GlobalScope.async {
urlFile.toStream(context)
}
// GlobalScope 2
val saved: Deferred<Uri?> = GlobalScope.async {
// get the downloaded bitmap
val fileStream : InputStream? = result.await()
// if downloaded then saved it to internal storage
Log.i(tag, "Stream collected, trying to save it") // <--- This is printing on the LogCat
fileStream?.saveToInternalStorage(context) // <-- This looks not to be executed!
}
// GlobalScope 3
GlobalScope.launch(Dispatchers.Main) {
val savedUri : Uri? = saved.await() // <-- This looks not to be executed!
Log.i(tag, "Stream saved")
val execFile = File(savedUri.toString())
Log.i(tag, "Setting file executable")
// execFile?.setExecutable(true)
Log.i(tag, "Running executable file")
// Runtime.getRuntime().exec(savedUri.toString())
// display saved bitmap to image view from internal storage
binding.imageView.setImageURI(savedUri)
// show bitmap saved uri in text view
binding.tvSaved.text = savedUri.toString()
it.isEnabled = true // enable button
binding.progressBar.visibility = View.INVISIBLE
}
}
}
}
The function that is running in the first scope is:
package com.example.dl
import android.content.Context
import android.util.Log
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
// extension function to get / download bitmap from url
fun URL.toStream(context : Context): InputStream? {
return try {
val tag = "Getting stream"
Log.i(tag, "Reading the stream from the web")
//this is the name of the local file you will create
val u = URL(this.toString())
val c = u.openConnection() as HttpURLConnection
c.requestMethod = "GET"
c.doOutput = true
c.connect()
c.inputStream
} catch (e: IOException){
null
}
}
The function that is running in the second scope, whihc looks to be no reached or not working properly, is:
package com.example.dl
import android.content.Context
import android.content.ContextWrapper
import android.net.Uri
import android.util.Log
import android.widget.Toast
import java.io.*
// extension function to save an image to internal storage
fun InputStream.saveToInternalStorage(context: Context): Uri?{
val tag = "Saving stream"
Log.i(tag, "Saving the stream from the web")
val targetFileName: String? = "server"
val wrapper = ContextWrapper(context)
var file = wrapper.getDir("images", Context.MODE_PRIVATE)
// create a file to save the downloaded one
file = File(file, targetFileName)
// get the file output stream
val stream: OutputStream = FileOutputStream(file)
Toast.makeText(context, "downloading", Toast.LENGTH_LONG).show()
var len1 = 0
return try {
// this.copyTo(stream)
var size: Long = 0
val buffer = ByteArray(1024)
Log.i(tag, "stream size ${this.readBytes().size}")
while (this.read(buffer).also { len1 = it } > 0) {
stream.write(buffer, 0, len1)
size += len1;
Log.i(tag, "file saved $size")
}
// flush the stream
stream.flush()
// close stream
stream.close()
this.close()
Log.i(tag, "file saved")
// compress bitmap
// compress(Bitmap.CompressFormat.JPEG, 100, stream)
// return the saved image uri
Uri.parse(file.absolutePath)
} catch (e: IOException){ // catch the exception
e.printStackTrace()
null
}
}