Skip to content

Commit a5d9aed

Browse files
committed
Add PDF printing support
1 parent 9789228 commit a5d9aed

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
buildscript {
22
extra.apply {
33
set("groupId", "com.kylecorry.andromeda")
4-
set("versionName", "10.2.0")
4+
set("versionName", "10.3.0")
55
set("targetVersion", 35)
66
set("compileVersion", 35)
77
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.kylecorry.andromeda.print
2+
3+
import android.net.Uri
4+
import android.os.Bundle
5+
import android.os.CancellationSignal
6+
import android.os.ParcelFileDescriptor
7+
import android.print.PageRange
8+
import android.print.PrintAttributes
9+
import android.print.PrintDocumentAdapter
10+
import android.print.PrintDocumentInfo
11+
import androidx.print.PrintHelper
12+
import java.io.FileInputStream
13+
import java.io.FileOutputStream
14+
import java.util.UUID
15+
16+
internal class PdfDocumentAdapter(private val uri: Uri, private val callback: PrintHelper.OnPrintFinishCallback) :
17+
PrintDocumentAdapter() {
18+
19+
override fun onLayout(
20+
oldAttributes: PrintAttributes?,
21+
newAttributes: PrintAttributes,
22+
cancellationSignal: CancellationSignal?,
23+
callback: LayoutResultCallback,
24+
bundle: Bundle
25+
) {
26+
if (cancellationSignal?.isCanceled == true) {
27+
callback.onLayoutCancelled()
28+
return
29+
} else {
30+
val builder =
31+
PrintDocumentInfo.Builder(
32+
uri.lastPathSegment ?: "${UUID.randomUUID()}.pdf"
33+
)
34+
builder.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
35+
.setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
36+
.build()
37+
38+
callback.onLayoutFinished(builder.build(), newAttributes == oldAttributes)
39+
}
40+
}
41+
42+
override fun onWrite(
43+
pageRanges: Array<out PageRange>,
44+
destination: ParcelFileDescriptor,
45+
cancellationSignal: CancellationSignal?,
46+
callback: WriteResultCallback
47+
) {
48+
try {
49+
// copy file from the input stream to the output stream
50+
FileInputStream(uri.path).use { inStream ->
51+
FileOutputStream(destination.fileDescriptor).use { outStream ->
52+
inStream.copyTo(outStream)
53+
}
54+
}
55+
56+
if (cancellationSignal?.isCanceled == true) {
57+
callback.onWriteCancelled()
58+
} else {
59+
callback.onWriteFinished(arrayOf(PageRange.ALL_PAGES))
60+
}
61+
62+
} catch (e: Exception) {
63+
callback.onWriteFailed(e.message)
64+
}
65+
}
66+
67+
override fun onFinish() {
68+
super.onFinish()
69+
callback.onFinish()
70+
}
71+
}

print/src/main/java/com/kylecorry/andromeda/print/Printer.kt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.kylecorry.andromeda.print
33
import android.content.Context
44
import android.graphics.Bitmap
55
import android.net.Uri
6+
import android.print.PrintAttributes
7+
import android.print.PrintManager
8+
import androidx.core.content.getSystemService
69
import androidx.print.PrintHelper
710
import kotlinx.coroutines.suspendCancellableCoroutine
811
import java.util.UUID
@@ -11,6 +14,8 @@ import kotlin.coroutines.resume
1114
class Printer(context: Context) {
1215

1316
private val helper = PrintHelper(context)
17+
private val printManager = context.getSystemService<PrintManager>()
18+
private val attributesBuilder = PrintAttributes.Builder()
1419

1520
fun setScaleMode(scaleMode: ScaleMode) {
1621
helper.scaleMode = when (scaleMode) {
@@ -24,13 +29,25 @@ class Printer(context: Context) {
2429
ColorMode.Color -> PrintHelper.COLOR_MODE_COLOR
2530
ColorMode.Monochrome -> PrintHelper.COLOR_MODE_MONOCHROME
2631
}
32+
attributesBuilder.setColorMode(
33+
when (colorMode) {
34+
ColorMode.Color -> PrintAttributes.COLOR_MODE_COLOR
35+
ColorMode.Monochrome -> PrintAttributes.COLOR_MODE_MONOCHROME
36+
}
37+
)
2738
}
2839

2940
fun setOrientation(orientation: Orientation) {
3041
helper.orientation = when (orientation) {
3142
Orientation.Portrait -> PrintHelper.ORIENTATION_PORTRAIT
3243
Orientation.Landscape -> PrintHelper.ORIENTATION_LANDSCAPE
3344
}
45+
attributesBuilder.setMediaSize(
46+
when (orientation) {
47+
Orientation.Portrait -> PrintAttributes.MediaSize.UNKNOWN_PORTRAIT
48+
Orientation.Landscape -> PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE
49+
}
50+
)
3451
}
3552

3653
fun print(bitmap: Bitmap, onFinished: (String) -> Unit = {}): String {
@@ -41,7 +58,16 @@ class Printer(context: Context) {
4158

4259
fun print(uri: Uri, onFinished: (String) -> Unit = {}): String {
4360
val jobName = createJobName()
44-
helper.printBitmap(jobName, uri) { onFinished(jobName) }
61+
// If it is a PDF, print it using the print manager
62+
if (uri.toString().endsWith(".pdf", true)) {
63+
printManager?.print(
64+
jobName,
65+
PdfDocumentAdapter(uri) { onFinished(jobName) },
66+
attributesBuilder.build()
67+
)
68+
} else {
69+
helper.printBitmap(jobName, uri) { onFinished(jobName) }
70+
}
4571
return jobName
4672
}
4773

0 commit comments

Comments
 (0)