|
@@ -1,151 +0,0 @@
|
|
|
-package com.hzliuzhi.applet.browser.print
|
|
|
-
|
|
|
-import android.content.Context
|
|
|
-import android.os.Bundle
|
|
|
-import android.os.CancellationSignal
|
|
|
-import android.os.ParcelFileDescriptor
|
|
|
-import android.print.PageRange
|
|
|
-import android.print.PrintAttributes
|
|
|
-import android.print.PrintDocumentAdapter
|
|
|
-import android.print.PrintDocumentInfo
|
|
|
-import android.print.PrintManager
|
|
|
-import android.webkit.WebView
|
|
|
-import com.google.gson.JsonElement
|
|
|
-import com.hzliuzhi.applet.core.shared.Payload
|
|
|
-import com.hzliuzhi.applet.core.shared.SharedFlowHub
|
|
|
-import com.hzliuzhi.applet.core.shared.SharedFlowHub.callbackAs
|
|
|
-import com.hzliuzhi.applet.core.shared.SharedFlowHub.cast
|
|
|
-import kotlinx.coroutines.CoroutineScope
|
|
|
-import kotlinx.coroutines.flow.filter
|
|
|
-import kotlinx.coroutines.flow.launchIn
|
|
|
-import kotlinx.coroutines.flow.onEach
|
|
|
-import okhttp3.Call
|
|
|
-import okhttp3.Callback
|
|
|
-import okhttp3.OkHttpClient
|
|
|
-import okhttp3.Request
|
|
|
-import okhttp3.Response
|
|
|
-import okio.buffer
|
|
|
-import okio.sink
|
|
|
-import java.io.File
|
|
|
-import java.io.FileInputStream
|
|
|
-import java.io.FileOutputStream
|
|
|
-import java.io.IOException
|
|
|
-
|
|
|
-class PrintEventHandle(webView: WebView, scope: CoroutineScope) {
|
|
|
- private val printManager: PrintManager = webView.context.getSystemService(Context.PRINT_SERVICE) as PrintManager
|
|
|
-
|
|
|
- init {
|
|
|
- android.util.Log.d("log:bridge", "PrintEventHandle 被注入")
|
|
|
- SharedFlowHub.events
|
|
|
- .filter { it.type.contains("print") }
|
|
|
- .onEach { _event ->
|
|
|
- when (_event.type) {
|
|
|
-
|
|
|
- "${SharedFlowHub.WEBVIEW_BRIDGE_EVENT}:print" -> {
|
|
|
- _event.cast<JsonElement, JsonElement>()?.also { event ->
|
|
|
- val print = event.payload?.let { it -> Print.formJson(it) }
|
|
|
- val callback = event.callback ?: {}
|
|
|
- handlePrint(webView, print) { payload ->
|
|
|
- payload.toJson()?.also { callback(it) }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- else -> _event.callbackAs<Payload<Unit>>()?.invoke(Payload.error(message = "[print] 未实现 ${_event.type}"))
|
|
|
- }
|
|
|
- }
|
|
|
- .launchIn(scope)
|
|
|
- }
|
|
|
-
|
|
|
- private fun handlePrint(webView: WebView, print: Print?, callback: ((Payload<Boolean?>) -> Unit)) {
|
|
|
- val attributes = PrintAttributes.Builder().build()
|
|
|
-
|
|
|
- print?.url.takeUnless { it.isNullOrEmpty() }?.also {
|
|
|
- val context = webView.context.applicationContext
|
|
|
- PdfPrintAdapter.download(
|
|
|
- context = context, print = print!!,
|
|
|
- onFinished = { file ->
|
|
|
- val jobName = "${context.getString(android.R.string.untitled)}_${file.name}"
|
|
|
- val adapter = PdfPrintAdapter(file, { callback(Payload.data(true));true }, { callback(Payload.error(message = it)); true })
|
|
|
- printManager.print(jobName, adapter, attributes)
|
|
|
- },
|
|
|
- onError = { callback(Payload.error(message = it)) }
|
|
|
- )
|
|
|
- } ?: webView.post {
|
|
|
- val jobName = "${webView.context.getString(android.R.string.untitled)}_page"
|
|
|
- val adapter = webView.createPrintDocumentAdapter("WebViewDocument")
|
|
|
- printManager.print(jobName, adapter, attributes)
|
|
|
- callback(Payload.data(true))
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-private class PdfPrintAdapter(
|
|
|
- private val file: File,
|
|
|
- private val onFinished: () -> Boolean = { true },
|
|
|
- private val onError: (String) -> Boolean = { true },
|
|
|
-) : PrintDocumentAdapter() {
|
|
|
- override fun onLayout(
|
|
|
- oldAttributes: PrintAttributes?,
|
|
|
- newAttributes: PrintAttributes?,
|
|
|
- cancellationSignal: CancellationSignal?,
|
|
|
- callback: LayoutResultCallback?,
|
|
|
- extras: Bundle?,
|
|
|
- ) {
|
|
|
- cancellationSignal?.takeIf { it.isCanceled }?.also { callback?.onLayoutCancelled(); return }
|
|
|
-
|
|
|
- PrintDocumentInfo.Builder(file.name).apply {
|
|
|
- setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
|
|
|
- setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
|
|
|
- }.build().also { callback?.onLayoutFinished(it, true) }
|
|
|
- }
|
|
|
-
|
|
|
- override fun onWrite(
|
|
|
- pages: Array<out PageRange>?,
|
|
|
- destination: ParcelFileDescriptor,
|
|
|
- cancellationSignal: CancellationSignal?,
|
|
|
- callback: WriteResultCallback?,
|
|
|
- ) {
|
|
|
- runCatching {
|
|
|
- FileInputStream(file).use { input ->
|
|
|
- FileOutputStream(destination.fileDescriptor).use { output ->
|
|
|
- input.copyTo(output)
|
|
|
- }
|
|
|
- }
|
|
|
- }.onSuccess {
|
|
|
- callback?.onWriteFinished(arrayOf(PageRange.ALL_PAGES))
|
|
|
- }.onFailure {
|
|
|
- callback?.onWriteFailed(it.message)
|
|
|
- onError("打印错误: ${it.message ?: "失败"}").takeIf { remove -> remove }?.also { file.delete() }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- override fun onFinish() {
|
|
|
- super.onFinish()
|
|
|
- onFinished().takeIf { remove -> remove }?.also { file.delete() }
|
|
|
- }
|
|
|
-
|
|
|
- companion object {
|
|
|
- fun download(context: Context, print: Print, onFinished: (File) -> Unit, onError: (String) -> Unit) {
|
|
|
- val request = Request.Builder().url(print.url!!).build()
|
|
|
- OkHttpClient().newCall(request).enqueue(object : Callback {
|
|
|
- override fun onFailure(call: Call, e: IOException) {
|
|
|
- onError("下载失败: IO 错误")
|
|
|
- }
|
|
|
-
|
|
|
- override fun onResponse(call: Call, response: Response) {
|
|
|
- if (!response.isSuccessful) onError("下载失败: ${response.message}").also { return }
|
|
|
- runCatching {
|
|
|
- File(context.cacheDir, "temp_${System.currentTimeMillis()}.pdf").apply {
|
|
|
- sink().buffer().use { sikp ->
|
|
|
- response.body?.source()?.let { sikp.writeAll(it) }
|
|
|
- }
|
|
|
- }
|
|
|
- }.onSuccess { onFinished(it) }.onFailure { onError("下载失败: ${it.message}") }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|