4

I'm trying to print a PDF file from my app's internal storage by sending it with an Intent.ACTION_SEND to the PrinterShare app (I've bought the premium version which claims to be able to print files from apps' internal storage).

I've looked at this, this and am copying my file to internal cache thanks to this and it seems that the PrinterShare app is getting my file, but not "completely" - it can't render the file and when I print, it just pushes out an empty file.

With the share intent, I can choose other apps like Gmail and plain Bluetooth and then I can send the PDF file as an email attachment or over Bluetooth to my personal phone and it renders perfectly. It's just when I try to share it to Google Photos, Hangouts and then also the PrinterShare app, that something goes weirdly wrong.

So how do you debug a problem that only happens sometimes?

Earlier on in my code I create the file in internal storage like this:

                val savePdf = File(view.filesDir, "printthis.pdf")

This is my share intent construction (Kotlin):

override fun printPdf() {
        copyFileToInternal()
        val uri = Uri.parse("content://my.package.android.app/printthis.pdf")
        Log.d("Print PDF from $uri")
        val shareIntent = Intent(Intent.ACTION_SEND)
        shareIntent.type = "image/*"
        shareIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
        (view as Context).startActivity(Intent.createChooser(shareIntent, "Print PDF"))
    }

This is the copyFileToInternal function:

private fun copyFileToInternal() {
    try {
        val inputStream = (view as Context).openFileInput("pop.pdf")

        val cacheDir = (view).cacheDir
        val outFile = File(cacheDir, "pop.pdf")
        val os = FileOutputStream(outFile.absolutePath)
        val buff = ByteArray(1024)
        var len: Int
        len = inputStream.read(buff)
        while (len > 0) {
            os.write(buff, 0, len)
            len = inputStream.read(buff)
        }
        os.flush()
        os.close()
        inputStream.close()

    } catch (e: IOException) {
        e.printStackTrace()
        Log.e("Could not copy file to internal cache. ", e)
    }
}

The only customisation on my ContentProvider is the openFile function:

@Throws(FileNotFoundException::class)
    override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
        val cacheDir = context.cacheDir
        val privateFile = File(cacheDir, "printthis.pdf")
        return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY)
    }

What am I missing?

marienke
  • 2,465
  • 4
  • 34
  • 66
  • 3
    First, the MIME type of PDF is not `image/*`. Second, call `getFD().sync()` on your `FileOutputStream` after `flush()` and before `close()`, to ensure that all bytes are written to disk before continuing. Third, please ensure that this I/O is performed on a background thread. Fourth, your problem might be in the `ContentProvider` that you are not showing in your question. – CommonsWare Oct 02 '17 at 15:20
  • Ah CommonsWare, you always come to the rescue when we miss silly things like MIME types. :) I've added the function I'm overriding in my custom ContentProvider – marienke Oct 02 '17 at 15:26
  • You might consider switching to using `FileProvider`, rather than rolling your own provider, and see if that helps. – CommonsWare Oct 02 '17 at 15:30
  • Your earlier suggestions now renders the PDF in the PrinterShare app, but now I have a problem actually connecting to the printer (#hardwarehassles) – marienke Oct 02 '17 at 15:32
  • Try unplugging and replugging in the Bluetooth cable. :-) – CommonsWare Oct 02 '17 at 15:37
  • You are a genius. :p – marienke Oct 02 '17 at 15:45

0 Answers0