android-Printing Content

In Android 4.4 (API level 19) and higher, the framework provides services for printing images and documents directly from Android applications. This training describes how to enable printing in your application, including printing images, HTML pages and creating custom documents for printing.

>Printing Photos

The Android Support Library PrintHelper class provides a simple way to print of images. The class has a single layout option, setScaleMode(), which allows you to print with one of two options:

  • SCALE_MODE_FIT - This option sizes the image so that the whole image is shown within the printable area of the page.
  • SCALE_MODE_FILL - This option scales the image so that it fills the entire printable area of the page. Choosing this setting means that some portion of the top and bottom, or left and right edges of the image is not printed. This option is the default value if you do not set a scale mode.
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);
}
》WebView: The Android framework provides a way to use HTML to compose a document and print it with a minimum of code.

In Android 4.4 (API level 19), the WebView class has been updated to enable printing HTML content. The class allows you to load a local HTML resource or download a page from the web, create a print job and hand it off to Android's print services.

Printing an HTML document with WebView involves loading an HTML resource or building an HTML document as a string. 

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 = "<html><body><h1>Test Content</h1><p>Testing, " +
            "testing, testing...</p></body></html>";
    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;
}

Note: Make sure your call for generating a print job happens in the onPageFinished() method of theWebViewClient you created in the previous section. If you don't wait until page loading is finished, the print output may be incomplete or blank, or may fail completely.

Note: The example code above holds an instance of the WebView object so that is it not garbage collected before the print job is created. Make sure you do the same in your own implementation, otherwise the print process may fail.

webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,
        "text/HTML", "UTF-8", null);
// Print an existing web page (remember to request INTERNET permission!):
webView.loadUrl("http://developer.android.com/about/index.html");

When using WebView for creating print documents, you should be aware of the following limitations:

  • You cannot add headers or footers, including page numbers, to the document.
  • The printing options for the HTML document do not include the ability to print page ranges, for example: Printing page 2 to 4 of a 10 page HTML document is not supported.
  • An instance of WebView can only process one print job at a time.
  • An HTML document containing CSS print attributes, such as landscape properties, is not supported.
  • You cannot use JavaScript in a HTML document to trigger printing.
private void createWebPrintJob(WebView webView) {

    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getActivity()
            .getSystemService(Context.PRINT_SERVICE);

    // Get a print adapter instance
    PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();

    // Create a print job with name and adapter instance
    String jobName = getString(R.string.app_name) + " Document";
    PrintJob printJob = printManager.print(jobName, printAdapter,
            new PrintAttributes.Builder().build());

    // Save the job object for later status checking
    mPrintJobs.add(printJob);
}
Printing Custom Documents

 The print output for these types of applications requires precise control of everything that goes into a page, including fonts, text flow, page breaks, headers, footers, and graphic elements.

You must build components that communicate with the print framework, adjust to printer settings, draw page elements and manage printing on multiple pages.

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); //
}

The PrintDocumentAdapter abstract class is designed to handle the printing lifecycle, which has four main callback methods. You must implement these methods in your print adapter in order to interact properly with the print framework:

  • onStart() - Called once at the beginning of the print process. If your application has any one-time preparation tasks to perform, such as getting a snapshot of the data to be printed, execute them here. Implementing this method in your adapter is not required.
  • onLayout() - Called each time a user changes a print setting which impacts the output, such as a different page size, or page orientation, giving your application an opportunity to compute the layout of the pages to be printed. At the minimum, this method must return how many pages are expected in the printed document.
  • onWrite() - Called to render printed pages into a file to be printed. This method may be called one or more times after each onLayout() call.
  • onFinish() - Called once at the end of the print process. If your application has any one-time tear-down tasks to perform, execute them here. Implementing this method in your adapter is not required.
》 Note:  These adapter methods are called on the main thread of your application. If you expect the execution of these methods in your implementation to take a significant amount of time, implement them to execute within a separate thread. For example, you can encapsulate the layout or print document writing work in separate  AsyncTask  objects.

The following code example shows a basic implementation of theonLayout() method for a PrintDocumentAdapter:

@Override
public void onLayout(PrintAttributes oldAttributes,
                     PrintAttributes newAttributes,
                     CancellationSignal cancellationSignal,
                     LayoutResultCallback callback,
                     Bundle metadata) {
    // Create a new PdfDocument with the requested page attributes
    mPdfDocument = new PrintedPdfDocument(getActivity(), newAttributes);

    // Respond to cancellation request
    if (cancellationSignal.isCancelled() ) {
        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.");
    }
}

The following code example shows an implementation where the number of pages is determined by the print orientation:

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);
}

Note: The Android print framework may call the onWrite() method one or more times for every call toonLayout(). For this reason, it is important to set the boolean parameter of onLayoutFinished() method to false when the print content layout has not changed, to avoid unnecessary re-writes of the print document.

Note: The boolean parameter of the onLayoutFinished() method indicates whether or not the layout content has actually changed since the last request. Setting this parameter properly allows the print framework to avoid unnecessarily calling the onLayout() method, essentially caching the previously written print document and improving performance.

The following sample demonstrates the basic mechanics of this process using the PrintedPdfDocument class to create a PDF file:

@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 = mPdfDocument.startPage(i);

            // check for cancellation
            if (cancellationSignal.isCancelled()) {
                callback.onWriteCancelled();
                mPdfDocument.close();
                mPdfDocument = null;
                return;
            }

            // Draw page content for printing
            drawPage(page);

            // Rendering is complete, so page can be finalized.
            mPdfDocument.finishPage(page);
        }
    }

    // Write PDF document to file
    try {
        mPdfDocument.writeTo(new FileOutputStream(
                destination.getFileDescriptor()));
    } catch (IOException e) {
        callback.onWriteFailed(e.toString());
        return;
    } finally {
        mPdfDocument.close();
        mPdfDocument = null;
    }
    PageRange[] writtenPages = computeWrittenPages();
    // Signal the print framework the document is complete
    callback.onWriteFinished(writtenPages);

    ...
}
When your application prints, your application must generate a PDF document and pass it to the Android print framework for printing. You can use any PDF generation library for this purpose. 

Also,This lesson shows how to use the PrintedPdfDocument class to generate PDF pages from your content.

The PrintedPdfDocument class uses a Canvas object to draw elements on an PDF page, similar to drawing on an activity layout. You can draw elements on the printed page using the Canvas draw methods. The following example code demonstrates how to draw some simple elements on a PDF document page using these methods:

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);
}
Tip:  While the  Canvas  object allows you to place print elements on the edge of a PDF document, many printers are not able to print to the edge of a physical piece of paper. Make sure that you account for the unprintable edges of the page when you build a print document with this class.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值