I work on application that create pdfs and can view them.
The problem is that for api 23->api 28, the application doesn't work as expected, I have a adapter with imageViews of first pdf page of last 5pdfs created by this app, and here is the problem, if I create pdfs without password, all works well, if I create 1 file with password, then all the files come like password protected files. And I get error java.lang.SecurityException: password required or incorrect password.
For android 9 and up all works ok. What can it be? please help
Here is the code:
CoroutineScope(Dispatchers.IO).launch {
try {
if (checkIfPdfIsPasswordProtected(Uri.fromFile(obj), context.contentResolver)) {
bitmapOfPdf = BitmapFactory.decodeResource(context.resources, R.drawable.camera)
} else {
bitmapOfPdf = pdfToBitmap(obj)!!
}
withContext(Dispatchers.Main) {
holder.binding.ivRecent.setImageBitmap(bitmapOfPdf)
}
} catch (e: Exception) {
Log.d("MainActiAdapter", e.message!!)
}
}
private fun checkIfPdfIsPasswordProtected(uri: Uri, contentResolver: ContentResolver): Boolean {
val parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")
?: return false
return try {
PdfRenderer(parcelFileDescriptor)
false
} catch (securityException: SecurityException) {
Log.e("CeErroare:", securityException.toString())
true
}catch (e:Exception){
false
}
}
private fun pdfToBitmap(pdfFile: File): Bitmap? {
val renderer =
PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY))
var bitmap: Bitmap? = null
try {
val pageCount = renderer.pageCount
if (pageCount > 0) {
val page = renderer.openPage(0)
val width = 136
val height = 146
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
page.close()
renderer.close()
}
} catch (ex: Exception) {
ex.printStackTrace()
renderer.close()
}
return bitmap
}
Related
I'm picking a file from the gallery and copying it to a specified folder. While copying I'm showing a ProgressDialog, I'm doing this with AsyncTask.
I'm trying to show the progress of the file being copied with percentage.
How can I get the current progress of the file being copied and display it as percentage ???
My code for copy file:
// Copy list file selected
for(i in 0 until arrayListCopyMoveFile.size){
if(arrayListCopyMoveFile.get(i).check){
copyFileOrDirectory(arrayListCopyMoveFile.get(i).file.path,path)
}
}
fun copyFileOrDirectory(srcDir: String?, dstDir: String?) {
try {
val src = File(srcDir)
val dst = File(dstDir, src.name)
if (src.isDirectory) {
val files = src.list()
val filesLength = files.size
for (i in 0 until filesLength) {
val src1 = File(src, files[i]).path
val dst1 = dst.path
copyFileOrDirectory(src1, dst1)
}
} else {
copyFile(src, dst)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
#Throws(IOException::class)
fun copyFile(sourceFile: File?, destFile: File) {
if (!destFile.parentFile.exists()) destFile.parentFile.mkdirs()
if (!destFile.exists()) {
destFile.createNewFile()
}
var source: FileChannel? = null
var destination: FileChannel? = null
try {
source = FileInputStream(sourceFile).getChannel()
destination = FileOutputStream(destFile).getChannel()
destination.transferFrom(source, 0, source.size())
} finally {
if (source != null) {
source.close()
}
if (destination != null) {
destination.close()
}
}
} ```
i have a probleme, i want to create a pdf and save him in download path on the phone, but it seems like there is an error and i don't know how to figure it out.
Can anyone help me please ? (I already have the permission for access storage, i think :/ ).
This is my code -->
fun createPdf
fun createPdf(
text: String,
context: Context
) {
val myPDFdocument = PdfDocument()
val myPaint = Paint()
val myPageInfo1 = PdfDocument.PageInfo.Builder(1240, 1754, 1).create()
val myPage1 = myPDFdocument.startPage(myPageInfo1)
val canvas = myPage1.canvas
canvas.drawText(text, 40F, 50F, myPaint)
myPDFdocument.finishPage(myPage1)
val file = File(context.externalCacheDir!!.absolutePath, "/FirstPdf.pdf")
try {
myPDFdocument.writeTo(FileOutputStream(file))
} catch (e: IOException) {
e.printStackTrace()
}
myPDFdocument.close()
}
I found the problem, here is the solution : (Principaly for android 11)
fun createPdf
val imageCollection =
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, "${commande}.pdf")
put(MediaStore.Downloads.MIME_TYPE, "application/pdf")
put(MediaStore.Downloads.IS_PENDING, 1)
}
val itemUri = resolver.insert(imageCollection, contentValues)
try {
Toast.makeText(context, "salut toi", Toast.LENGTH_SHORT).show()
resolver.insert(imageCollection, contentValues)?.also { uri ->
resolver.openOutputStream(uri).use { outputStream ->
myPDFdocument.writeTo(outputStream)
}
}
contentValues.clear()
contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(itemUri!!, contentValues, null, null)
myPDFdocument.close()
} catch (e: IOException) {
e.printStackTrace()
}
I am Saving the Path to an Image that is set by the user, when the app starts up from cold the image path is read from file and is(should be displayed) but it doesn't want to show. is there a simpler method to reading a set image from gallery?
This is my read File, within this Internal file I am saving a String Path to the Image
fun readDataLocally(context: Context, FileName: String): String {
var str = ""
try {
val inputStream = context.openFileInput(FileName)
if (inputStream != null) {
val inputStreamReader = InputStreamReader(inputStream)
val bufferedReader = BufferedReader(inputStreamReader)
val partialStr = StringBuilder()
var done = false
while (!done) {
val line = bufferedReader.readLine()
done = (line == null)
if (line != null) partialStr.append(line)
}
inputStream.close()
str = partialStr.toString()
}
} catch (e: FileNotFoundException) {
Log.e("Error: ", "file not found: " + e.toString())
} catch (e: IOException) {
Log.e("Error: ", "cannot read file: " + e.toString())
}
Log.d("FileRead",str)
return str
}
This reads the Image path and sets the bit map, any time I call this method it causes the Exception E.
fun readImageFromPath(context: Context, path : String) : Bitmap? {
var bitmap : Bitmap? = null
val uri = Uri.parse(path)
Log.d("path",path)
if (uri != null) {
try {
val parcelFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")
val fileDescriptor = parcelFileDescriptor?.fileDescriptor
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
parcelFileDescriptor?.close()
} catch (e: Exception) {
Toast.makeText(context,"Image Read is unavailable please reload",Toast.LENGTH_SHORT).show()
}
}
Log.d("Rip", bitmap.toString())
return bitmap
}
Methods used too call Image to show on Activity Start Up
ImageView.setImageBitmap(readImageFromPath(this,readDataLocally(this, "HomeImage")))
and I tried
val bitmap = readDataLocally(this, "HomeImage")
ManagerScreen_Image.setImageBitmap(readImageFromPath(this, bitmap))
I have the Correct Manifest Permissions.
Basically, I am trying to download three different images(bitmaps) from a URL and save them to Apps Internal storage, and then use the URI's from the saved file to save a new Entity to my database. I am having a lot of issues with running this in parallel and getting it to work properly. As ideally all three images would be downloaded, saved and URI's returned simultaneously. Most of my issues come from blocking calls that I cannot seem to avoid.
Here's all of the relevant code
private val okHttpClient: OkHttpClient = OkHttpClient()
suspend fun saveImageToDB(networkImageModel: CBImageNetworkModel): Result<Long> {
return withContext(Dispatchers.IO) {
try {
//Upload all three images to local storage
val edgesUri = this.async {
val req = Request.Builder().url(networkImageModel.edgesImageUrl).build()
val response = okHttpClient.newCall(req).execute() // BLOCKING
val btEdges = BitmapFactory.decodeStream(response.body?.byteStream())
return#async saveBitmapToAppStorage(btEdges, ImageType.EDGES)
}
val finalUri = this.async {
val urlFinal = URL(networkImageModel.finalImageUrl) // BLOCKING
val btFinal = BitmapFactory.decodeStream(urlFinal.openStream())
return#async saveBitmapToAppStorage(btFinal, ImageType.FINAL)
}
val labelUri = this.async {
val urlLabels = URL(networkImageModel.labelsImageUrl)
val btLabel = BitmapFactory.decodeStream(urlLabels.openStream())
return#async saveBitmapToAppStorage(btLabel, ImageType.LABELS)
}
awaitAll(edgesUri, finalUri, labelUri)
if(edgesUri.getCompleted() == null || finalUri.getCompleted() == null || labelUri.getCompleted() == null) {
return#withContext Result.failure(Exception("An image couldn't be saved"))
}
} catch (e: Exception) {
Result.failure<Long>(e)
}
try {
// Result.success( db.imageDao().insertImage(image))
Result.success(123) // A placeholder untill I actually get the URI's to create my Db Entity
} catch (e: Exception) {
Timber.e(e)
Result.failure(e)
}
}
}
//Save the bitmap and return Uri or null if failed
private fun saveBitmapToAppStorage(bitmap: Bitmap, imageType: ImageType): Uri? {
val type = when (imageType) {
ImageType.EDGES -> "edges"
ImageType.LABELS -> "labels"
ImageType.FINAL -> "final"
}
val filename = "img_" + System.currentTimeMillis().toString() + "_" + type
val file = File(context.filesDir, filename)
try {
val fos = file.outputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (e: Exception) {
Timber.e(e)
return null
}
return file.toUri()
}
Here I am calling this function
viewModelScope.launch {
val imageID = appRepository.saveImageToDB(imageNetworkModel)
withContext(Dispatchers.Main) {
val uri = Uri.parse("$PAINT_DEEPLINK/$imageID")
navManager.navigate(uri)
}
}
Another issue I am facing is returning the URI in the first place and handling errors. As if one of these parts fails, I'd like to cancel the whole thing and return Result.failure(), but I am unsure on how to achieve that. As returning null just seems meh, I'd much prefer to have an error message or something along those lines.
I am trying to capture the image using 2 different lenses (wide and normal). The preview works fine for both cameras simultaneously using the new multicamera support in Camera2API. I am using Huawei Mate20Pro.
However, when I capture the picture, it only saves pink colored JPEG images. But when the object is close enough, the picture is captured perfectly. Here is what I mean. This is how a pink JPEG looks like:
However, when the object is close enough, the capture is fine. Here is how it looks like:
Here is the main activity code:
button.setOnClickListener {
if (isRunning) {
handler.removeCallbacksAndMessages(null)
restartActivity()
} else {
button.text = "Stop"
handler.postDelayed(object : Runnable {
override fun run() {
twoLens.reset()
twoLens.isTwoLensShot = true
MainActivity.cameraParams.get(dualCamLogicalId).let {
if (it?.isOpen == true) {
Logd("In onClick. Taking Dual Cam Photo on logical camera: $dualCamLogicalId")
takePicture(this#MainActivity, it)
Toast.makeText(applicationContext, "Captured!", Toast.LENGTH_SHORT).show()
}
}
handler.postDelayed(this, 1000)
}
}, 2000)
}
isRunning = !isRunning
}
}
Here is the picture capture code.
fun captureStillPicture(activity: MainActivity, params: CameraParams) {
if (!params.isOpen) {
return
}
try {
Logd("In captureStillPicture.")
val camera = params.captureSession?.getDevice()
if (null != camera) {
params.captureBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
params.captureBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
if (params.id.equals(dualCamLogicalId) && twoLens.isTwoLensShot) {
val normalParams: CameraParams? = MainActivity.cameraParams.get(normalLensId)
val wideParams: CameraParams? = MainActivity.cameraParams.get(wideAngleId)
if (null == normalParams || null == wideParams)
return
Logd("In captureStillPicture. This is a Dual Cam shot.")
params.captureBuilder?.addTarget(normalParams.imageReader?.surface!!)
params.captureBuilder?.addTarget(wideParams.imageReader?.surface!!)
params.captureBuilder?.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 4)
params.captureBuilder?.set(CaptureRequest.JPEG_QUALITY, 100)
if (Build.VERSION.SDK_INT >= 28) { params.captureBuilder?.set(CaptureRequest.DISTORTION_CORRECTION_MODE, CameraMetadata.DISTORTION_CORRECTION_MODE_OFF)
//This is REQUIRED to disable HDR+ on Pixel 3 - even though Pixel 3 doesn't have sepia
params.captureBuilder?.set(CaptureRequest.CONTROL_EFFECT_MODE, CameraMetadata.CONTROL_EFFECT_MODE_SEPIA)
} else {
//This is REQUIRED to disable HDR+ on Pixel 3 - even though Pixel 3 doesn't have sepia
params.captureBuilder?.set(CaptureRequest.CONTROL_EFFECT_MODE, CameraMetadata.CONTROL_EFFECT_MODE_SEPIA)
Logd("DUAL CAM DEBUG: I am setting sepia mode.")
// Logd("DUAL CAM DEBUG: I am NOT setting sepia mode.")
}
val rotation = activity.getWindowManager().getDefaultDisplay().getRotation()
var capturedImageRotation = getOrientation(params, rotation)
params.captureBuilder?.set(CaptureRequest.JPEG_ORIENTATION, capturedImageRotation)
try {
params.captureSession?.stopRepeating()
// params.captureSession?.abortCaptures()
} catch (e: CameraAccessException) {
e.printStackTrace()
}
//Do the capture
// TODO: Capture BURST HERE
if (28 <= Build.VERSION.SDK_INT)
params.captureSession?.captureSingleRequest(params.captureBuilder?.build(), params.backgroundExecutor, StillCaptureSessionCallback(activity, params))
else
params.captureSession?.capture(params.captureBuilder?.build(), StillCaptureSessionCallback(activity, params),
params.backgroundHandler)
}
} catch (e: CameraAccessException) {
e.printStackTrace()
} catch (e: IllegalStateException) {
Logd("captureStillPicture IllegalStateException, aborting: " + e)
}
}
This is how I am grabbing the captured pictures.
fun getImagesCaptured(activity: MainActivity, twoLens: TwoLensCoordinator){
Logd("Normal image timestamp: " + twoLens.normalImage?.timestamp)
Logd("Wide image timestamp: " + twoLens.wideImage?.timestamp)
val wideBuffer: ByteBuffer? = twoLens.wideImage!!.planes[0].buffer
val wideBytes = ByteArray(wideBuffer!!.remaining())
wideBuffer.get(wideBytes)
val normalBuffer: ByteBuffer? = twoLens.normalImage!!.planes[0].buffer
val normalBytes = ByteArray(normalBuffer!!.remaining())
normalBuffer.get(normalBytes)
val options = BitmapFactory.Options()
val wideMat: Mat = Mat(twoLens.wideImage!!.height, twoLens.wideImage!!.width, CvType.CV_8UC1)
val tempWideBitmap = BitmapFactory.decodeByteArray(wideBytes, 0, wideBytes.size, options)
val normalMat: Mat = Mat(twoLens.normalImage!!.height, twoLens.normalImage!!.width, CvType.CV_8UC1)
val tempNormalBitmap = BitmapFactory.decodeByteArray(normalBytes, 0, normalBytes.size, options)
save(normalBytes, "NormalShot")
save(wideBytes, "WideShot")
}
The save function is here.
fun save(bytes: Bitmap, tempName: String) {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val dataDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "TwoCameraImages")
if (!dataDir.exists()) {
dataDir.mkdir()
}
val fileName = tempName + "_IMG_$timeStamp.jpg"
val fileDir = File(dataDir.path + File.separator + fileName)
try {
val fileOutputStream = FileOutputStream(fileDir)
bytes.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
//fileOutputStream.write(bytes)
fileOutputStream.close()
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
I built on top of code given here: https://github.com/google/basicbokeh and switched to rear cameras, and removed the face calculations. But this pink bitmap is not going away. Any help?