I'm trying to download file via Retrfoit and everything goes well, until I'm opening it, because after that the only things that I see either a black screen (for images) or some kid of error about wrong file format. Can you tell me what am I doing wrong?
File creation sources:
val file = File(getExternalFilesDir(null), event.fileName)
ResponseBody converting sources:
private fun writeResponseBodyToDisk(body: ResponseBody, file: File): Boolean {
return try {
// todo change the file location/name according to your needs
val futureStudioIconFile: File = file
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
try {
val fileReader = ByteArray(4096)
val fileSize: Long = body.contentLength()
var fileSizeDownloaded: Long = 0
inputStream = body.byteStream()
outputStream = FileOutputStream(futureStudioIconFile)
while (true) {
val read: Int = inputStream.read(fileReader)
if (read == -1) {
break
}
outputStream.write(fileReader, 0, read)
fileSizeDownloaded += read.toLong()
Timber.d("%s%s", "file download: $fileSizeDownloaded of ", fileSize)
}
outputStream.flush()
viewState.value = ViewState.ShowFile(file)
true
} catch (e: IOException) {
false
} finally {
inputStream?.close()
outputStream?.close()
}
} catch (e: IOException) {
false
}
}
Viewwing sources:
val fileUri = FileProvider.getUriForFile(
this,
"${BuildConfig.APPLICATION_ID}.fileprovider",
state.file
)
startActivity(
Intent.createChooser(
Intent().apply {
action = Intent.ACTION_VIEW
putExtra(Intent.EXTRA_STREAM, fileUri)
clipData = ClipData.newRawUri("", fileUri)
type = "*/*"
addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
},
null
)
)
Logs:
file download: 4096 of 21688
file download: 8192 of 21688
file download: 12288 of 21688
file download: 16384 of 21688
file download: 20480 of 21688
file download: 21688 of 21688
Related
I cannot open the pdf file I downloaded from the internet on my android device.
It gives the error that the file is corrupt. (corrupt file opens in pc)
//Request;
#GET("url")
suspend fun getDocumentDownload(#Path("File") file: String?): Response<ResponseBody>
//writeResponseBodyToDisk
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
val byteArray = ByteArray(4096)
val fileSize = body.contentLength()
var fileSizeDownloaded: Long = 0
inputStream = body.byteStream()
outputStream = FileOutputStream(file)
while (true) {
val read = inputStream.read(byteArray)
if (read == -1) {
break
}
outputStream.write(byteArray, 0, read)
fileSizeDownloaded += read.toLong()
}
outputStream.flush()
Response corrupt;
Response success;
Iam trying to open a saved pdf file from the internal cache dir.
In the "old" way my code looked liked this.
In jetpack compose i can use this part of code, the pdf is beeining created and i can see it in the device explorer. But how can i display the pdf on screen ?
fun decodeTestPdfString(pdf_string:String, context:Context) {
//make FileOutPutStream
var fos: FileOutputStream? = null
try {
if (pdf_string != null) {
f = File(context?.cacheDir, "testFile" + ".pdf")
f!!.createNewFile()
fos = FileOutputStream(f)
val decodedString: ByteArray = Base64.decode(pdf_string, Base64.DEFAULT)
fos.write(decodedString)
fos.flush()
fos.close()
}
} catch (e: Exception) {
} finally {
if (fos != null) {
fos = null
}
}
val path: Uri = FileProvider.getUriForFile(context!!, context!!.getApplicationContext().getPackageName() + ".provider", f!!)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(path, "application/pdf")
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
}
}
}
But the last step (try intent) is giving an issue.
The file is created in the cache dir, i can see it.
To open the pdf reader:
startActivity(context, intent, options:null)
I'm using below code for downloading the image and it download successfully but not showing in galary please help!!!
I have tried couple of examples none of them are working..
I have also tried the MediaScanner to scan the file and update the gallery
If anyone have links related this question please share
class DownloadFileFromURL : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void): Void? {
var count: Int
try {
val url = URL(getUrl())
val conection: URLConnection = url.openConnection()
conection.connect()
// input stream to read file - with 8k buffer
val input: InputStream = BufferedInputStream(url.openStream(), 8192)
val output: OutputStream?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver: ContentResolver = activity?.contentResolver!!
val contentValues = ContentValues()
val name = System.currentTimeMillis()
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$name.jpg")
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
output = imageUri?.let { resolver.openOutputStream(it) }!!
} else {
val imgFile = createImageFile()
if (!imgFile.exists()) {
imgFile.createNewFile()
}
output = FileOutputStream(imgFile)
}
// Output stream to write file
val data = ByteArray(1024)
var total: Long = 0
while (input.read(data).also { count = it } != -1) {
total += count.toLong()
// writing data to file
output.write(data, 0, count)
}
// flushing output
output.flush()
// closing streams
output.close()
input.close()
} catch (e: Exception) {
Log.e("Error: ", e.message)
}
return null
}
override fun onPostExecute(result: Void?) {
downloadComplete()
}
#Throws(IOException::class)
private fun createImageFile(): File {
// Create an image file name
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
val storageDir: File = activity?.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
return File(
storageDir, /* directory */
"JPEG_${timeStamp}"+ /* prefix */
".jpg" /* suffix */
).apply {
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = absolutePath
}
}
}
I tried saving video to gallery like i found on example:
private fun saveVideoToInternalStorage3(filePath: String) {
val newfile: File
try {
val currentFile = File(filePath)
val fileName = currentFile.name
val cw = ContextWrapper(applicationContext)
val directory = cw.getDir("videoDir", Context.MODE_PRIVATE)
newfile = File(directory.absolutePath, fileName)
if(currentFile.exists()) {
val `in`: InputStream = FileInputStream(currentFile)
val out: OutputStream = FileOutputStream(newfile)
// Copy the bits from instream to outstream
val buf = ByteArray(1024)
var len: Int
while(`in`.read(buf).also {len = it} > 0) {
out.write(buf, 0, len)
}
scanner(filePath)
`in`.close()
out.close()
Log.d("", "Video file saved successfully.")
Toast.makeText(this, "Push Video Saved TO Gallery", Toast.LENGTH_SHORT).show()
} else {
Log.d("", "Video saving failed. Source file missing.")
}
} catch(e: java.lang.Exception) {
Log.d("", "EXS " + e.message)
e.printStackTrace()
}
And it works fine it shows message "Video file saved successfully." But there is no video in my gallery.
After searching for problem i found post that says you need a scanner and i tried:
private fun scanner(path: String) {
MediaScannerConnection.scanFile(this, arrayOf(path), null, object: OnScanCompletedListener {
override fun onScanCompleted(path: String, uri: Uri?) {
Log.i("", "Finished scanning $path")
}
})
But still no luck. Does any1 know what is going on? Saving images in gallery works fine btw.
I'm using Storage Access Network to pick file and save in internal storage so that app can use if in future.
I'm getting URI without any issues. It's something like content://com.android.providers.media.documents/document/image%3A141274
Problem comes when I'm trying to save image into internal directory. Code passes without crashes, image with same size is saved into internal directory (I can see it in device Explorer: https://take.ms/3TwBS).
But image itself is broken and can't be opened.
Here's code I'm using (after getting URI)
val destinationFile = File("${context.filesDir.absolutePath}/$fileName")
try {
val writer = FileWriter(destinationFile)
writer.append(readTextFromUri(it))
writer.flush()
writer.close()
} catch (e: Exception) {
e.printStackTrace()
}
#Throws(IOException::class)
private fun readTextFromUri(uri: Uri): String {
val inputStream = activity!!.contentResolver.openInputStream(uri)
val reader = BufferedReader(InputStreamReader(inputStream))
val stringBuilder = StringBuilder()
var line: String? = null
while ({ line = reader.readLine(); line }() != null) {
stringBuilder.append(line)
}
inputStream?.close()
reader.close()
return stringBuilder.toString()
}
As #CommonsWare described I should have used proper dealing with files, not texts.
Proper way to do:
private fun inputStreamToFile(uri: Uri){
val inputStream = contentResolver.openInputStream(uri)
val output = FileOutputStream(File("${filesDir.absoluteFile}/magic.png"))
inputStream?.copyTo(output, 4 * 1024)
}
Or longer way (without extension functions)
fun inputStreamToFile(uri: Uri){
val inputStream = contentResolver.openInputStream(uri)
inputStream.use {
val directory = getDir("test", Context.MODE_PRIVATE)
val file = File(directory, "correct.txt")
val output = FileOutputStream(file)
output.use {
val buffer = ByteArray(4 * 1024) // or other buffer size
var read: Int = inputStream?.read(buffer) ?: -1
while (read != -1) {
output.write(buffer, 0, read)
read = inputStream?.read(buffer) ?: -1
}
output.flush()
}
}
}