how to open pdf file from internal cache dir jetpack compose - android

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)

Related

Android: Writing byteArray into file

I'm trying to write a byteArray received from a server. This is my code
private fun writePdf(content: ByteArray) {
val storageDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
val file = File("${storageDir?.path}/", "${Date().time}Download.pdf")
try {
// file.writeBytes(archivo)
val os = FileOutputStream(file, false)
os.write(content)
os.flush()
os.close()
} catch (e: IOException) {
e.printStackTrace()
}
val intent = Intent(Intent.ACTION_VIEW)
val uri = FileProvider
.getUriForFile(
this,
this.packageName + ".fileprovider",
file)
intent.setDataAndType(uri, "application/pdf")
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
try{
startActivity(intent)
}catch (e: Exception){
e.printStackTrace()
Toast.makeText(this, "Error", Toast.LENGTH_LONG)
.show()
}
}
The problem is that when the pdf opens it is blank, like nothing has been written.
I've tried writing with FileOutputStream and File.writeBytes.
I've checked the byteArray (in case is corrupted or something) and it has no problems.
I've checked the length() of the file before and after writing, and it's length increases accordingly.
Thanks, any kind of help is appreciated.
I finally found the problem, and solution. Everything with the code above was okay; the problem was that the flags for the intent to visualize the PDF were wrong. Instead of:
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
It should be:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

How to move a temporarily picture taken from camera to SD-Card on Android with Kotlin

my App collecting some data from the user including an optional picture. To getting a High-Res picture i'm using following code:
https://medium.com/codex/how-to-use-the-android-activity-result-api-for-selecting-and-taking-images-5dbcc3e6324b
Getting the picture works as expected. If the user click on a save button, all data shall be written to an CSV-File on the SD-Card, and if latestTmpUri not null the user made a picture as well, and should be saved to the SD-Card, also.
I tried some snippets to move a file on Android, but everytime i'll get an error "File not exists". Maybe it has to do with path in provider_paths.xml, but i'm not sure.
By the way, i'm newbee on programming in Kotlin for Android.
EDIT:
If you take a look in the code from the URL above, there is an deleteOnExit()
private fun getTmpFileUri(): Uri {
val tmpFile = File.createTempFile("tmp_image_file", ".png", cacheDir).apply {
createNewFile()
deleteOnExit()
}
return FileProvider.getUriForFile(applicationContext, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}
And if you look in provider_paths.xml
<cache-path name="cached_files" path="." />
<files-path name="images" path="." />
This is the path of the picture
content://com.company.contacts.provider/cached_files/tmp_image_file580022157706292749.png
To give an other path in <cache-path name="cached_files" path="." /> is not the solution i guess, because the SD-CARD's got a unique identifier, like E534-12F6
After a bit of research and thinking about FileInputStream and FileOutputStream and reading this post
https://stackoverflow.com/a/11327789/10155771
i got my solution. Depending on the Code in my first post to take a High-Res picture i modified it in this way:
private lateinit var tmpFile: File
private fun getTmpFileUri(): Uri {
tmpFile = File.createTempFile("tmp_image_file", ".png", cacheDir).apply {
createNewFile()
deleteOnExit()
}
return FileProvider.getUriForFile(applicationContext, "${BuildConfig.APPLICATION_ID}.provider", tmpFile)
}
to make the variable tmpFile global.
In my function to save the CSV and the optional picture i did this:
var imageName = ""
if(latestTmpUri != null) { // There was taken a picture if not null
val folder = getExternalFilesDirs(Environment.DIRECTORY_PICTURES)
val root = java.lang.String.valueOf(folder[1]).toString() // folder[1] is my SD-Card while folder[0] is internal storage
val filets: String = java.lang.String.valueOf(
TimeUnit.MILLISECONDS.toSeconds(
System.currentTimeMillis()
)
) // Unix Timestamp
imageName = companyContact +"_$filets.png"
var instream: InputStream? = null
var outstream: OutputStream? = null
try {
val dir: File = File(root, imageName.replace(" ", "_"))
instream = FileInputStream(tmpFile.path)
outstream = FileOutputStream(dir.path)
val buffer = ByteArray(1024)
var read: Int
while (instream!!.read(buffer).also { read = it } != -1) {
outstream!!.write(buffer, 0, read)
}
instream.close()
instream = null
outstream!!.flush()
outstream.close()
outstream = null
} catch (fnfe1: FileNotFoundException) {
fnfe1.message?.let { it1 -> Log.e("FileNotFoundException", it1) }
} catch (e: java.lang.Exception) {
Log.e("Exception", e.message!!)
}
}
Now i have my picture as png on my SD-Card.
Here is a simple solution for Kotlin 1.7.X
// move Uri file from cache to app's external files
// - from: data/data/com.example.myapp/cache/videos/file.mp4
// - to: sdcard/Android/data/com.example.myapp/files/Movies
// Note: not selectable by the user.
fun moveUriFileToAppMovies(fromUri: Uri, context: Context) {
val inputStream = context.contentResolver.openInputStream(fromUri)!!
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_MOVIES),
fromUri.lastPathSegment ?: "video.mp4")
val outputStream = FileOutputStream(file)
inputStream.copyTo(outputStream)
inputStream.close()
outputStream.close()
}

Pdf intent not showing file

I'm trying to display in the pdf intent of android an file using his Uri, but it seems that I always get an blank pdf and don't know why, can someone give me some advice why.
Code:
private fun pdfConverter(pdfFile: DtoSymptomCheckerPdf?) {
val documentsPath = File(context?.filesDir, "documents")
if(!documentsPath.exists()){
documentsPath.mkdir()
}
val file = File(documentsPath, pdfFile?.filename)
val pdfAsBytes: ByteArray = android.util.Base64.decode(pdfFile?.file, 0)
val os = FileOutputStream(file,false)
os.write(pdfAsBytes)
os.flush()
os.close()
println("EL CONTENT: " + file.length())
val uri = FileProvider.getUriForFile(App.applicationContext,
BuildConfig.APPLICATION_ID + ".provider", file)
val pdfIntent = Intent(Intent.ACTION_VIEW)
pdfIntent.setDataAndType(uri, "application/pdf")
pdfIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
try {
startActivity(pdfIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(requireContext(), "Can't read pdf file",
Toast.LENGTH_SHORT).show()
}
}

Unable to Save an Image and See It in My Gallery

I have a Bitmap image that I want to save and have it show up in my gallery, unfortunately I am having a lot of issues trying to complete this task. Since yesterday I've probably tried a dozen different code snippets to do just this. I think what's happening is that these code snippets are working, but they're saving it in the application's data and not in the shared storage/gallery.
How do I re-adapt this code to have it store images in a folder that any gallery application or file manager can access and not just in the application's data?
private fun saveToGallery(bitmap: Bitmap) {
Toast.makeText(applicationContext,"Saving image!", Toast.LENGTH_SHORT).show()
var outputStream: FileOutputStream? = null
val file = Environment.getExternalStorageDirectory()
val dir = File(file.absolutePath.toString() + "/MyPics")
dir.mkdirs()
val filename = String.format("%d.png", System.currentTimeMillis())
val outFile = File(dir, filename)
try {
outputStream = FileOutputStream(outFile)
} catch (e: Exception) {
e.printStackTrace()
}
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
try {
outputStream!!.flush()
} catch (e: Exception) {
e.printStackTrace()
}
try {
outputStream!!.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
You should send a broadcast event after saving the image.
For example:
https://stackoverflow.com/a/39448816/5313283

error exposed beyond app through Intent, open pdf file

Through base64 string iam creating a pdf file.
This pdf file is succesfully created and stored in data/users/0/cache
On a button click i want to show this pdf file.
Function in kotlin:
fun decodeArbeidscontractString() {
var fos: FileOutputStream? = null
try {
f = File(context?.cacheDir, "newPdf_f.pdf")
f!!.createNewFile()
fos = FileOutputStream(f)
val decodedString: ByteArray = Base64.decode(pdf_string_arbeidscontract,
Base64.DEFAULT)
fos.write(decodedString) //write the base64 to the pdf
fos.flush()
fos.close()
val path: Uri = Uri.fromFile(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) {
}
}
I can see the file in the emulator but cannot open it. How can i do that

Categories

Resources