android 6.0 webview 加载js_61、android打印文件

6a785bcb7bf3906960a9bd79b9d3dcfd.png

Android 用户经常只在他们的设备上查看内容,但有时将屏幕显示给某人看并不足以分享信息。借助从 Android 应用打印信息的功能,用户可以查看您的应用内容的更大版本,或与未使用您的应用的其他人分享内容。通过打印,用户还可以创建信息的快照,不受是否拥有设备、电池电量是否充足或是否具有无线网络连接的影响。

在 Android 4.4(API 级别 19)及更高版本中,Android 框架提供直接从 Android 应用打印图片和文档的服务。本次培训介绍了如何在应用中启用打印功能,包括打印图片、HTML 页面和创建要打印的自定义文档。

1、打印照片

拍摄和分享照片是移动设备最受欢迎的用途之一。如果您的应用可以拍照、显示照片或允许用户分享图片,您应该考虑支持在您的应用中打印这些图片。Android 支持库提供了一个便捷的功能,用于使用最少量的代码和简单的打印版式选项集合来支持图片打印。

下面介绍如何使用 v4 支持库 PrintHelper 类打印图片。

打印图片

Android 支持库 PrintHelper 类提供了一种简单的图片打印方式。该类具有单个版式选项 setScaleMode(),可让您通过以下两个选项之一进行打印:

  • SCALE_MODE_FIT - 此选项用于调整图片大小,使整个图片显示在页面的可打印区域内。

  • SCALE_MODE_FILL - 此选项用于缩放图片,使其填充页面的整个可打印区域。选择此设置意味着图片上下或左右边缘的某些部分不会打印出来。如果您未设置缩放模式,则此选项为默认值。

setScaleMode() 的这两个缩放选项都能保持图片的现有宽高比不变。以下代码示例演示了如何创建 PrintHelper 类的实例、设置缩放选项以及开始打印过程:

  private void doPhotoPrint() {        PrintHelper photoPrinter = new PrintHelper(getActivity());        photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),                R.drawable.droids);        photoPrinter.printBitmap("droids.jpg - test print", bitmap);    }    

此方法可以作为菜单项的操作来调用。请注意,对于并非始终受支持的操作(如打印),相应的菜单项应放置在溢出菜单中。如需了解详情,请参阅操作栏设计指南。

调用 printBitmap() 方法后,不需要从您的应用中执行进一步操作。此时会显示 Android 打印界面,允许用户选择打印机和打印选项。然后,用户可以打印图片或取消操作。如果用户选择打印图片,则会创建打印作业并在系统栏中显示打印通知。

2、打印 HTML 文档

如需在 Android 上打印简单照片之外的内容,需要在打印文档中撰写文本和添加图形。在 Android 框架中,您可以使用 HTML 以最少的代码撰写文档并进行打印。

在 Android 4.4(API 级别 19)中,WebView 类已更新,可支持打印 HTML 内容。该类使您能够加载本地 HTML 资源或从网络上下载网页,创建打印作业并将其移交给 Android 的打印服务。

本节课介绍如何快速构建包含文本和图形的 HTML 文档,并使用 WebView 打印该文档。

加载 HTML 文档

要使用 WebView 打印 HTML 文档,需要加载 HTML 资源或以字符串形式构建 HTML 文档。本部分介绍如何构建 HTML 字符串并将其加载到 WebView 进行打印。

此视图对象通常用作 Activity 布局的一部分。但是,如果您的应用未使用 WebView,则可以专门为打印目的而创建该类的实例。创建此自定义打印视图的主要步骤如下:

  1. 创建在加载 HTML 资源后启动打印任务的 WebViewClient

  2. 将 HTML 资源加载到 WebView 对象中。

以下代码示例演示了如何创建简单的 WebViewClient 并加载即时创建的 HTML 文档:  

 private WebView mWebView;    private void doWebViewPrint() {        // Create a WebView object specifically for printing        WebView webView = new WebView(getActivity());        webView.setWebViewClient(new WebViewClient() {                public boolean shouldOverrideUrlLoading(WebView view, String url) {                    return false;                }                @Override                public void onPageFinished(WebView view, String url) {                    Log.i(TAG, "page finished loading " + url);                    createWebPrintJob(view);                    mWebView = null;                }        });        // Generate an HTML document on the fly:        String htmlDocument = "

Test Content

Testing, "

+ "testing, testing..."; webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null); // Keep a reference to WebView object until you pass the PrintDocumentAdapter // to the PrintManager mWebView = webView; }

如需在页面中添加图形,请将图形文件放在项目的 assets/ 目录中,并在 loadDataWithBaseURL() 方法的第一个参数中指定基准网址,如以下代码示例所示:

  webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,            "text/HTML", "UTF-8", null);    

您还可以将 loadDataWithBaseURL() 方法替换为 loadUrl(),以加载要打印的网页,如下所示。

  // Print an existing web page (remember to request INTERNET permission!):    webView.loadUrl("http://developer.android.com/about/index.html");    

使用 WebView 创建打印文档时,应注意以下限制:

  • 您不能向文档中添加页眉或页脚,包括页码。

  • HTML 文档的打印选项不包括打印特定范围的页面,例如:不支持打印一个 10 页 HTML 文档中的第 2 到 4 页。

  • WebView 的实例一次只能处理一个打印作业。

  • 不支持包含 CSS 打印属性(例如横向属性)的 HTML 文档。

  • 您不能在 HTML 文档中使用 JavaScript 触发打印作业。

创建打印作业

创建 WebView 并加载 HTML 内容之后,您的应用即将完成它那部分的打印流程。接下来的步骤是访问 PrintManager,创建打印适配器,最后创建打印作业。以下示例说明了如何执行这些步骤:

 private void createWebPrintJob(WebView webView) {        // Get a PrintManager instance        PrintManager printManager = (PrintManager) getActivity()                .getSystemService(Context.PRINT_SERVICE);        String jobName = getString(R.string.app_name) + " Document";        // Get a print adapter instance        PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(jobName);        // Create a print job with name and adapter instance        PrintJob printJob = printManager.print(jobName, printAdapter,                new PrintAttributes.Builder().build());        // Save the job object for later status checking        printJobs.add(printJob);    }    

此示例保存了 PrintJob 对象的实例供应用使用,这不是必需的。您的应用可能会使用此对象跟踪正在处理的打印作业的进度。当您希望监控应用中打印作业的状态(完成、失败或用户取消)时,此方法很有用。不需要创建应用内通知,因为打印框架会自动为打印任务创建系统通知。

打印自定义文档

对于某些应用,例如绘图应用、页面布局应用以及专注于图形输出的其他应用,创建精美的打印页面是一项重要功能。在这种情况下,打印图片或 HTML 文档是不够的。对于此类应用,打印输出需要精确控制进入页面的所有内容,包括字体、文本流、分页符、页眉、页脚和图形元素。

比起之前讨论的方法,创建完全针对您的应用自定义的打印输出需要投入更多的编程工作。您必须构建与打印框架通信的组件,根据打印机设置做出调整,绘制页面元素以及管理多页打印。

本节课将向您介绍如何连接打印管理器、创建打印适配器和构建打印内容。

连接到打印管理器

当应用直接管理打印过程时,从用户那收到打印请求后的第一步是连接到 Android 打印框架并获取 PrintManager 类的实例。该类使您能够初始化打印作业并开始打印生命周期。以下代码示例演示了如何获取打印管理器并开始打印过程。

    private void doPrint() {        // Get a PrintManager instance        PrintManager printManager = (PrintManager) getActivity()                .getSystemService(Context.PRINT_SERVICE);        // Set job name, which will be displayed in the print queue        String jobName = getActivity().getString(R.string.app_name) + " Document";        // Start a print job, passing in a PrintDocumentAdapter implementation        // to handle the generation of a print document        printManager.print(jobName, new MyPrintDocumentAdapter(getActivity()),                null); //    }

以上示例代码演示了如何命名打印作业和设置处理打印生命周期步骤的 PrintDocumentAdapter 类的实例。下一部分将讨论打印适配器类的实现。

创建打印适配器

打印适配器与 Android 打印框架互动,并处理打印过程的步骤。此过程要求用户在创建打印文档前先选择打印机和打印选项。当用户选择具有不同输出功能、不同页面大小或不同页面方向的打印机时,这些选择会影响最终输出。在进行这些选择时,打印框架会要求您的适配器设置布局并生成打印文档,为最终输出做准备。当用户点按打印按钮后,框架将接受最终打印文档并将其传递给打印提供器以进行输出。在打印过程中,用户可以选择取消打印操作,因此打印适配器还必须监听和回应取消请求。

PrintDocumentAdapter 抽象类旨在处理打印生命周期,它有四个主要的回调方法。您必须在打印适配器中实现这些方法,才能与打印框架正确交互:

  • onStart() - 在打印过程开始时调用一次。如果应用有任何一次性准备任务要执行,例如获取要打印的数据的快照,请在此处执行这些任务。无需在适配器中实现此方法。

  • onLayout() - 每当用户更改影响输出的打印设置(例如不同的页面大小或页面方向)时调用,让应用有机会计算要打印的页面的布局。此方法至少必须返回打印文档预期的页数。

  • onWrite() - 调用它来将打印的页面呈现为要打印的文件。在每次调用 onLayout() 之后,可能调用此方法一次或多次。

  • onFinish() - 在打印过程结束时调用一次。如果您的应用有任何一次性拆解任务要执行,请在此处执行这些任务。无需在适配器中实现此方法。

以下几部分介绍了如何实现布局和写入方法,这些方法对于打印适配器的正常运行至关重要。

计算打印文档信息

在 PrintDocumentAdapter 类的实现中,您的应用必须能够指定要创建的文档的类型,并根据打印页面尺寸的相关信息计算打印作业的总页数。在适配器中实现的 onLayout() 方法可完成这些计算,并在 PrintDocumentInfo 类中提供有关打印作业预期输出的信息,包括页数和内容类型。以下代码示例演示了 PrintDocumentAdapter 的 onLayout() 方法的基本实现:

   @Override    public void onLayout(PrintAttributes oldAttributes,                         PrintAttributes newAttributes,                         CancellationSignal cancellationSignal,                         LayoutResultCallback callback,                         Bundle metadata) {        // Create a new PdfDocument with the requested page attributes        pdfDocument = new PrintedPdfDocument(getActivity(), newAttributes);        // Respond to cancellation request        if (cancellationSignal.isCanceled() ) {            callback.onLayoutCancelled();            return;        }        // Compute the expected number of printed pages        int pages = computePageCount(newAttributes);        if (pages > 0) {            // Return print information to print framework            PrintDocumentInfo info = new PrintDocumentInfo                    .Builder("print_output.pdf")                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)                    .setPageCount(pages)                    .build();            // Content layout reflow is complete            callback.onLayoutFinished(info, true);        } else {            // Otherwise report an error to the print framework            callback.onLayoutFailed("Page count calculation failed.");        }    }    

执行 onLayout() 方法可能会产生三种结果:完成、取消或失败(在无法完成布局计算的情况下)。您必须通过调用 PrintDocumentAdapter.LayoutResultCallback 对象的相应方法指明其中一种结果。

onLayout() 的主要工作是根据打印机的属性计算预计输出的页数。计算此数字的方式在很大程度上取决于应用的打印页面布局。在以下代码示例所示的实现中,页数取决于打印方向:

 private int computePageCount(PrintAttributes printAttributes) {        int itemsPerPage = 4; // default item count for portrait mode        MediaSize pageSize = printAttributes.getMediaSize();        if (!pageSize.isPortrait()) {            // Six items per page in landscape orientation            itemsPerPage = 6;        }        // Determine number of print items        int printItemCount = getPrintItemCount();        return (int) Math.ceil(printItemCount / itemsPerPage);    }

写入打印文档文件

到了要将打印输出写入文件时,Android 打印框架会调用应用的 PrintDocumentAdapter 类的 onWrite() 方法。该方法的参数指定应写入的页面以及要使用的输出文件。然后,此方法的实现必须将每个请求的内容页呈现为多页 PDF 文档文件。此过程完成后,您需要调用回调对象的 onWriteFinished() 方法。

以下示例演示了该过程的基本机制,并使用 PrintedPdfDocument 类创建 PDF 文件:

 @Override    public void onWrite(final PageRange[] pageRanges,                        final ParcelFileDescriptor destination,                        final CancellationSignal cancellationSignal,                        final WriteResultCallback callback) {        // Iterate over each page of the document,        // check if it's in the output range.        for (int i = 0; i < totalPages; i++) {            // Check to see if this page is in the output range.            if (containsPage(pageRanges, i)) {                // If so, add it to writtenPagesArray. writtenPagesArray.size()                // is used to compute the next output page index.                writtenPagesArray.append(writtenPagesArray.size(), i);                PdfDocument.Page page = pdfDocument.startPage(i);                // check for cancellation                if (cancellationSignal.isCanceled()) {                    callback.onWriteCancelled();                    pdfDocument.close();                    pdfDocument = null;                    return;                }                // Draw page content for printing                drawPage(page);                // Rendering is complete, so page can be finalized.                pdfDocument.finishPage(page);            }        }        // Write PDF document to file        try {            pdfDocument.writeTo(new FileOutputStream(                    destination.getFileDescriptor()));        } catch (IOException e) {            callback.onWriteFailed(e.toString());            return;        } finally {            pdfDocument.close();            pdfDocument = null;        }        PageRange[] writtenPages = computeWrittenPages();        // Signal the print framework the document is complete        callback.onWriteFinished(writtenPages);        ...    }

此示例将 PDF 页面内容的呈现委托给 drawPage() 方法,详见下一部分的讨论。

和布局一样,执行 onWrite() 方法可能会产生三种结果:完成、取消或失败(在无法写入内容的情况下)。您必须通过调用 PrintDocumentAdapter.WriteResultCallback 对象的相应方法来指明其中一种结果。

绘制 PDF 页面内容

当应用进行打印时,应用必须生成 PDF 文档并将其传递到 Android 打印框架进行打印。您可以将任何 PDF 生成库用于此目的。本节课介绍如何使用 PrintedPdfDocument 类根据您的内容生成 PDF 页面。

PrintedPdfDocument 类使用 Canvas 对象在 PDF 页面上绘制元素,类似于在 Activity 布局上绘制。您可以使用 Canvas 绘制方法在打印页上绘制元素。以下示例代码演示了如何使用以下方法在 PDF 文档页面上绘制一些简单的元素:

private void drawPage(PdfDocument.Page page) {        Canvas canvas = page.getCanvas();        // units are in points (1/72 of an inch)        int titleBaseLine = 72;        int leftMargin = 54;        Paint paint = new Paint();        paint.setColor(Color.BLACK);        paint.setTextSize(36);        canvas.drawText("Test Title", leftMargin, titleBaseLine, paint);        paint.setTextSize(11);        canvas.drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint);        paint.setColor(Color.BLUE);        canvas.drawRect(100, 100, 172, 172, paint);    }

使用 Canvas 在 PDF 页面上绘制时,元素以磅(即 1/72 英寸)为单位进行指定。请确保使用此度量单位指定页面上元素的大小。对于已绘制元素的位置,坐标系从页面左上角的 (0,0) 处开始。

提示:虽然 Canvas 对象允许在 PDF 文档的边缘放置打印元素,但许多打印机无法打印到实际纸张的边缘。当您使用该类构建打印文档时,确保考虑到页面的不可打印边缘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值