Android 在 NativeScript 中实现 PDF 打印

Android implementation for PDF printing in NativeScript

在我的 NativeScript-Vue 应用程序中,我需要将 PDF 文档打印到蓝牙打印机,并在打印成功或取消时收到回调。插件 nativescript-printer handles it flawlessly on iOS, but on Android it doesn't return a callback (the feature is not implemented). The plugin uses the class PrintHelper,它有一个在成功和取消时都会调用的回调,没有参数和 return.

看来只能通过classPrintManager来实现打印了。一些来源:

这就是我尝试过的。 onWriteonLayout 有效,但 onStartonFinish(这是我的目标)从未被调用。

import * as application from "tns-core-modules/application";

function printPdf(pdfFilePath) { // path: "/data/user/0/com.myapp.test/cache/pdf/document1.pdf"
    let printManager = application.android.foregroundActivity.getSystemService(android.content.Context.PRINT_SERVICE);
    let jobName = "PrintPdf";
    let PrintPDFAdapter = android.print.PrintDocumentAdapter.extend({
        onStart() {
            console.log("on start);
        },

        onWrite(pages, destination, cancellationSignal, callback) {
            let input;
            let output;
            try {
                input = new java.io.FileInputStream(new java.io.File(pdfFilePath));
                output = new java.io.FileOutputStream(destination.getFileDescriptor());

                let buf = new Array.create("byte", 1024);
                let bytesRead;
                while ((bytesRead = input.read(buf)) > 0) {
                    output.write(buf, 0, bytesRead);
                }

                callback.onWriteFinished(new android.print.PageRange(0, 0));
            } catch (e){
                console.error(e);
            } finally {
                try {
                    input.close();
                    output.close();
                } catch (e) {
                    console.error(e);
                }
            }
        },

        onLayout(oldAttributes, newAttributes, cancellationSignal, callback, extras){
            try {
                if (cancellationSignal.isCanceled()) {
                    callback.onLayoutCancelled();
                    return;
                }

                let pdi = new android.print.PrintDocumentInfo.Builder("print_output.pdf").setContentType(android.print.PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();

                callback.onLayoutFinished(pdi, true);
            } catch (e) {
                console.error(e);
            }
        },

        onFinish() {
            console.log("on finish");
        }
    });

    let pda = new PrintPDFAdapter();

    printManager.print(jobName, pda, null);
}

printManager.print() returns 一个 PrintJob 对象,它公开了当前的打印状态。这不太好,但这是我的解决方法:

function printPDF(pdfFilePath) {

    // above code

    let printJob = printManager.print(jobName, pda, null);

    let onFinish = function(status) {
        resolve(status);
        clearInterval(interval);
    }
    let interval = setInterval(() => {
        let state = printJob.getInfo().getState();
        console.log(state);
        if (state === 6) onFinish("print failed");
        if (state === 7) onFinish("print cancelled");
        if (state === 5) onFinish("print completed");
    }, 500);
}

如果 PrintJob 状态卡在排队或阻塞状态,我可能会在间隔上实施超时。