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来实现打印了。一些来源:
- Printing custom documents | Android Developers
- An Android Custom Document Printing Tutorial
- Printing PDF directly using PrintManager Android 4.4
- How to Print PDF using Android 4.4 Printing framework(有很多赞成票,这似乎是最佳答案)
这就是我尝试过的。 onWrite
和 onLayout
有效,但 onStart
和 onFinish
(这是我的目标)从未被调用。
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 状态卡在排队或阻塞状态,我可能会在间隔上实施超时。
在我的 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来实现打印了。一些来源:
- Printing custom documents | Android Developers
- An Android Custom Document Printing Tutorial
- Printing PDF directly using PrintManager Android 4.4
- How to Print PDF using Android 4.4 Printing framework(有很多赞成票,这似乎是最佳答案)
这就是我尝试过的。 onWrite
和 onLayout
有效,但 onStart
和 onFinish
(这是我的目标)从未被调用。
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 状态卡在排队或阻塞状态,我可能会在间隔上实施超时。