Android PrintManager: процесс завершается, выводимый на печать файл имеет длину нулевых байтовAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android PrintManager: процесс завершается, выводимый на печать файл имеет длину нулевых байтов

Сообщение Anonymous »

Вот пример кода. Это просто: он берет PDF-файл из ресурсов и отправляет его на стандартный принтер. Он основан на этом руководстве Google с минимальными изменениями (я не обрабатываю подкачку должным образом, но это не имеет значения).

Код: Выделить всё

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

findViewById(R.id.button).setOnClickListener{ Printer().print(this) }
//...
}
//...
}

class Printer {

fun print(context : Context) {
log("Printer.print")
val printManager = context.getSystemService(Context.PRINT_SERVICE) as PrintManager

val attrib = PrintAttributes.Builder()
.setMediaSize(PrintAttributes.MediaSize.ISO_A4)
.build()

printManager.print("Test print job name", SampleDocumentAdapter(context, "sample.pdf"), attrib)
log("Printer.print done")
}

private inner class SampleDocumentAdapter(
private val context : Context,
private val assetFileName: String
) : PrintDocumentAdapter(){

override fun onStart() {
log("SampleDocumentAdapter.onStart")
super.onStart()
}

override fun onFinish() {
log("SampleDocumentAdapter.onFinish")
super.onFinish()
}

override fun onLayout(oldAttrs: PrintAttributes?, newAttrs: PrintAttributes,cancelSignal: CancellationSignal,
callback: LayoutResultCallback, extra: Bundle?)
{
log("SampleDocumentAdapter.onLayout")
if (cancelSignal.isCanceled) {
callback.onLayoutCancelled()
} else {
PrintDocumentInfo.Builder("Test printer output")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.build()
.also {
callback.onLayoutFinished(it, true)
}
}
log("SampleDocumentAdapter.onLayout done")
}

override fun onWrite(pages: Array?, destination: ParcelFileDescriptor,
cancelSignal: CancellationSignal, callback: WriteResultCallback)
{
log("SampleDocumentAdapter.onWrite")
CoroutineScope(Dispatchers.IO).launch {
launch {
log("SampleDocumentAdapter.onWrite async")

try {
context.assets.open(assetFileName).use { inStream ->
val buffer = ByteArray(16384)

FileOutputStream(destination.fileDescriptor).use { outStream ->
var totalBytes = 0
while (true) {
val length = inStream.read(buffer)
if (length < 0) break
outStream.write(buffer, 0, length)
totalBytes += length
}
log("SampleDocumentAdapter.onWrite - total of $totalBytes bytes written")
}
}

destination.close()
callback.onWriteFinished(arrayOf(PageRange.ALL_PAGES))

log("SampleDocumentAdapter.onWrite done")
} catch (e: Exception){
log("SampleDocumentAdapter.onWrite error $e")
callback.onWriteFailed("SampleDocumentAdapter.onWrite error $e")
}
}
}

log("SampleDocumentAdapter.onWrite done")
}
}
}
Вот полный код. Вы также можете скачать полный репозиторий, если хотите.
Я использую симулятор принтера «Сохранить как PDF» для тестирования.
Проблема. Пока пользователь выполняет процедуру печати (параметры печати, выбор файла для сохранения и т. д.), он переключается на другое приложение в другом процессе (скорее всего, причиной является приложение выбора файлов Google). Мое приложение переходит в фоновый режим. Иногда, но не всегда, это приводит к тому, что мое приложение закрывается ОС (поскольку мы работаем в фоновом режиме, не так ли?).
Если это произойдет, нет подходящего способа обработка из платформы PrintManager. Framework по-прежнему использует наш код (часть SampleDocumentAdapter) в качестве обратного вызова для получения данных печати, но когда мы умираем, ему все равно. В результате я получаю выходной файл для печати (pdf) длиной 0 байт и без каких-либо сообщений об ошибках. Никакой SampleDocumentAdapter.onFinish не вызывается (хотя SampleDocumentAdapter.onWrite обычно работает правильно). Вся структура PrintManager, похоже, не имеет какого-либо инструмента для правильной обработки жизненного цикла приложения, она просто ломается.
В stackoverflow слишком мало тем, связанных с печатью, поэтому я в инете не нашел советов. Мне также не удалось найти ни одного абзаца в документации, указывающего на подобную проблему. В моем реальном проекте мне удалось обойти эту проблему, используя поддельную службу переднего плана, чтобы предотвратить завершение моего процесса, но это выглядит довольно хакерским решением для такой простой задачи.
Вопрос: правда ли, что Google допустил такую ​​ошибку в таком простом случае, или я просто что-то пропустил в документации?

Подробнее здесь: https://stackoverflow.com/questions/782 ... bytes-leng
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»