Blog logo Icon menu
Multiple page printing from a HTML Adobe AIR Application

Adobe AIR PrintingIt's been almost two months since Adobe released its first official version of Adobe Integrated Runtime -- AIR 1.0. AIR provides a pretty flexible way for development of desktop-like applications by the use of web technologies: HTML / JavaScript, and Flash / Flex. In other words AIR allows web programmers to develop desktop applications. I speak from my own experience when I say that web developers have a hard time developing desktop applications.

I'm not sure what is behind this mysterious fact, but it's so hard for most of the web geeks to develop a desktop apps (and perhaps vice versa). However, AIR seems to be something that all of us were waiting for a long time. It's still version numero uno, but it seems to be working quite well.
There are a lot of things to be done and we are positive that they gonna happen pretty soon, since the web development community became very fond of AIR. To leave a side the Flash developers who seem to adjust nicely in every OO environment, the even webbies can now go much deeper, and don't have to change their means.

Recently, we've got a project to develop a desktop application for "electronic reports" generation. Electronic reports are text files that contain a report in a specific predefined format.
Anyway, the application had to allow the user to enter data, and once the user would finish he'd be able to save the file and print the report on a paper. You can use SQLite as a Database with your AIR application, manipulate it through your JavaScript code and that seemed like a perfect solution. This was a great opportunity to actually dive into the AIR world. Everything went smooth till the print part.
First of all, HTML AIR applications don't support window.print() function. We've spent a lot of time looking for something on the net, someone that had similar experience and perhaps might found a solution. And we did find something (simulates window.print function) that simulates single page printing. However this is not what we needed since it is limited to a single page printing. Our reports were few pages long so we had to extend the solution, or come up with a different one. We did quite of experiments, and following is what came to as a possible solution.
AIR is based on Flash functionalities, and if you are developing HTML AIR application then the HTML is rendered through the WebKit open source web browser engine. Since the native window.print() functionality is not available, you'll have to use flash.printing tools. You can access it in your HTML/JavaScript AIR application through window.runtime.flash.printing.*. Also, you must bear in mind that you are able to print any Sprite, but in our case that's the window.htmlLoader. A great disadvantage is that you must explicitily state all the pages you want to print and define a rectangle area of the Sprite (htmlLoader). In other words you have to prepare and populate every single page that you want to print, and then send it to the printer by using addPage().
Here are the steps you must complete for a printing job:

  1. Create a printJob (new window.runtime.flash.printing.PrintJob;)
  2. Create/Define a print Sprite, in our case that's the window.htmlLoader
  3. Create printing options (new window.runtime.flash.printing.PrintJobOptions;)
  4. Start the printJob (pjob.start())
  5. Go through the pages you want to print, prepare them and add them for printing (pjob.addPage())
  6. Send the print job to the printer (pjob.send())

Important note is that you must set printAsBitmap to true in the printing options, since that is the only way to get something printed. The htmlLoader (all of your HTML) is printed as Bitmap, and that is quite a limitation since you get a blury print. Since we had to make quite of preprint preparations we decided to actually open a new application window which would handle the printing and actually never show that window. Once the printing was finished we'd close the window. Here is the complete code for such a solution:

 // You might find useful to pass some value, number of rows for instance
function multiplePagePrint(numRows)
{
  // Create the Print Job
  var pjob = new window.runtime.flash.printing.PrintJob;
  var psprite = window.htmlLoader; // Define the Sprite
  if ( pjob.start() ) // Start the Print Job
    {
      // Define the Print Job Options
      var poptions = new window.runtime.flash.printing.PrintJobOptions;
      poptions.printAsBitmap = true; // Must print it as Bitmap

      //after you've start the print job
      // you can get any print specifics (page size etc.)
      var pageHeight = pjob.pageHeight;
      var pageWidth = pjob.pageWidth;
      var paperHeight = pjob.paperHeight;
      var paperWidth = pjob.paperWidth;

      // Calculate the number of pages
      var pagesToPrint = /** Your logic here **/;

      // Add your pages:
      for(var i = 0; i < pagesToPrint; i++)
      {
	/** Your logic here for calculating RECT_HEIGHT **/
        var rect = new air.Rectangle(0, RECT_HEIGHT, pageWidth, pageHeight);

        try{
          pjob.addPage(psprite, rect, poptions);
        } catch(e) {
          air.trace(e);
        }
      }

      try
      {
        pjob.send();
        return true;
      }
      catch (err)
      {
        air.trace(err);
        return false;
      }
    }
    else
    {
      air.trace("PrintJob couldn't start");
      return false;
    }
}

As I've mentioned above the print is done in a separate application window which you can open with air.NativeWindow(), and here you can call your function. It handles all of the print activities, it is never being activated, that is, it is invisible to the user all the time, it starts the print, adds pages and prints, and once the print is done it is being closed. This way the user gets the system print interactive window for selecting the printer, number of copies to be printed etc.
Since our reports were mostly text reports we can't say that this solution is perfect. As a matter of fact it is not, and I'll advise you not to use it if you have to print text. However, it demonstrates the possibility of a multiple page printing in a HTML AIR application. The print results we got when printing in a Flash AIR application were far more superior. Some flash development in the current version of AIR is definitely recommended, at least if you need to print some text. I hope in future we gonna get improvements in AIR when it comes to printing in HTML AIR applications, and at least get the native window.print() functionality.

I strongly advice you to go through the ActionScript 3.0 Language and Components Reference even if you are a stubborn HTML / JavaScript developer, since the only thing that can happen is an extra benefit for your development skills.

Share this article:
Comments