2

I am printing pdf using the below code which works fine for normal pdfs but crashes with password-protected pdf. is there any way by which we can print password-protected pdf or stop applications from crashing. application crashes even print() called inside a try-catch block.

Exception :

java.lang.RuntimeException: 
  at android.print.PrintManager$PrintDocumentAdapterDelegate$MyHandler.handleMessage (PrintManager.java:1103)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8506)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1139)

code that causing Exception:

val printManager = this.getSystemService(Context.PRINT_SERVICE) as PrintManager
        val jobName = this.getString(R.string.app_name) + " Document"
        try{
            printManager.print(jobName, pda, null)
        }
        catch(ex:RuntimeException)
        {
            Toast.makeText(this,"Can't print pdf file",Toast.LENGTH_SHORT).show()
        }

PrintDocumentAdapter.kt

  var pda: PrintDocumentAdapter = object : PrintDocumentAdapter() {
    
            override fun onWrite(
                    pages: Array<PageRange>,
                    destination: ParcelFileDescriptor,
                    cancellationSignal: CancellationSignal,
                    callback: WriteResultCallback
            ) {
                var input: InputStream? = null
                var output: OutputStream? = null
                try {
                    input = uri?.let { contentResolver.openInputStream(it) }
    
                    output = FileOutputStream(destination.fileDescriptor)
                    val buf = ByteArray(1024)
                    var bytesRead: Int
                    if (input != null) {
                        while (input.read(buf).also { bytesRead = it } > 0) {
                            output.write(buf, 0, bytesRead)
                        }
                    }
                    callback.onWriteFinished(arrayOf(PageRange.ALL_PAGES))
                } catch (ee: FileNotFoundException) {
                    //Code to Catch FileNotFoundException
                } catch (e: Exception) {
                   //Code to Catch exception
                } finally {
                    try {
                        input!!.close()
                        output!!.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                }
            }
    
            override fun onLayout(
                    oldAttributes: PrintAttributes,
                    newAttributes: PrintAttributes,
                    cancellationSignal: CancellationSignal,
                    callback: LayoutResultCallback,
                    extras: Bundle
            ) {
                if (cancellationSignal.isCanceled) {
                    callback.onLayoutCancelled()
                    return
                }
                val pdi = PrintDocumentInfo.Builder("Name of file")
                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build()
                callback.onLayoutFinished(pdi, true)
            }
        }

OR if not possible then how to get password removed from pdf.

Saurabh Dhage
  • 1,478
  • 5
  • 17
  • 31
  • You can use `iText` (https://itextpdf.com/en) to generate an encrypted pdf. – Kamal Nayan Aug 13 '21 at 08:28
  • @KamalNayan no I want to print encrypted pdfs or handle this exception. – Saurabh Dhage Aug 13 '21 at 08:39
  • To print encrypted pdf you can use `iText`. It's a trusted library. – Kamal Nayan Aug 13 '21 at 09:00
  • @kamalNayan due to some reasons i don't want to use itext i just want to print protected pdf – Saurabh Dhage Aug 13 '21 at 11:34
  • Then you can encrypt and decrypt pdf file then open it in the pdfViewer. – Kamal Nayan Aug 13 '21 at 11:45
  • @kamalNayan my concern is not about opening or encrypting it is about printing – Saurabh Dhage Aug 13 '21 at 11:49
  • but printing involves a subprocess in `PrintDocumentAdapter ` and you have issues in that class... so it will affect that – Kamal Nayan Aug 13 '21 at 11:57
  • Printing in Android is designed for content generated from Android. It is not designed for arbitrary PDFs, let alone password-protected ones. If you insist on continuing down this path, you would need to create a copy of the PDF that lacks the password (by some means), then print the copy. – CommonsWare Aug 28 '21 at 16:25
  • @CommonsWare so is there any way by which we can make copy of pdf without password – Saurabh Dhage Aug 28 '21 at 16:36
  • I would skim through a search on `java remove password from pdf` in your favorite search engine. You seem to be opposed to iText, which will limit your options. There may be recipes using Apache PDFBox. – CommonsWare Aug 28 '21 at 16:37
  • @CommonsWare how can I catch exceptions thrown in while printing. it's not getting caught even if placed inside a try-catch block. eg. RuntimeException – Saurabh Dhage Aug 29 '21 at 15:48
  • @SaurabhDhage: It is possible that there is no place to catch such exceptions -- it will depend on where they are thrown. Without seeing a stack trace, though, I cannot really provide any suggestions. – CommonsWare Aug 29 '21 at 15:54
  • @CommonsWare I have provided the stack trace in question – Saurabh Dhage Aug 29 '21 at 15:59
  • Sorry, but that stack trace seems to be incomplete. Are you certain that is the entire stack trace, and there are no "Caused by" sections after what you posted? – CommonsWare Aug 29 '21 at 16:02
  • @CommonsWare yes this is the only stack trace generated by play console – Saurabh Dhage Aug 29 '21 at 16:04

2 Answers2

1
pdfView.fromAsset(String)
    .pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default
    .enableSwipe(true) // allows to block changing pages using swipe
    .swipeHorizontal(false)
    .enableDoubletap(true)
    .defaultPage(0)
    // allows to draw something on the current page, usually visible in the middle of the screen
    .onDraw(onDrawListener)
    // allows to draw something on all pages, separately for every page. Called only for visible pages
    .onDrawAll(onDrawListener)
    .onLoad(onLoadCompleteListener) // called after document is loaded and starts to be rendered
    .onPageChange(onPageChangeListener)
    .onPageScroll(onPageScrollListener)
    .onError(onErrorListener)
    .onPageError(onPageErrorListener)
    .onRender(onRenderListener) // called after document is rendered for the first time
    // called on single tap, return true if handled, false to toggle scroll handle visibility
    .onTap(onTapListener)
    .onLongPress(onLongPressListener)
    .enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
    .password(null)
    .scrollHandle(null)
    .enableAntialiasing(true) // improve rendering a little bit on low-res screens
    // spacing between pages in dp. To define spacing color, set view background
    .spacing(0)
    .autoSpacing(false) // add dynamic spacing to fit each page on its own on the screen
    .linkHandler(DefaultLinkHandler)
    .pageFitPolicy(FitPolicy.WIDTH) // mode to fit pages in the view
    .fitEachPage(false) // fit each page to the view, else smaller pages are scaled relative to largest page.
    .pageSnap(false) // snap pages to screen boundaries
    .pageFling(false) // make a fling change only a single page like ViewPager
    .nightMode(false) // toggle night mode
    .load();

Have you tried updating the ".password" line?

Arda Kazancı
  • 8,341
  • 4
  • 28
  • 50
0

You need not to generate pdf without password to print. as you said you are using barteksc:android-pdf-viewer for viewing pdfs which uses PDfium for rendering pdf which has a method to render bitmap from method.

void getBitmaps() {
    ImageView iv = (ImageView) findViewById(R.id.imageView);
    ParcelFileDescriptor fd = ...;
    int pageNum = 0;
    PdfiumCore pdfiumCore = new PdfiumCore(context);
    try {
        PdfDocument pdfDocument = pdfiumCore.newDocument(fd);

        pdfiumCore.openPage(pdfDocument, pageNum);

        int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNum);
        int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNum);

        // ARGB_8888 - best quality, high memory usage, higher possibility of OutOfMemoryError
        // RGB_565 - little worse quality, twice less memory usage
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        pdfiumCore.renderPageBitmap(pdfDocument, bitmap, pageNum, 0, 0,
                width, height);
        //if you need to render annotations and form fields, you can use
        //the same method above adding 'true' as last param

        iv.setImageBitmap(bitmap);

        printInfo(pdfiumCore, pdfDocument);

        pdfiumCore.closeDocument(pdfDocument); // important!
    } catch(IOException ex) {
        ex.printStackTrace();
    }
}

store these bitmaps in arraylist and print them using android print framework