Android KitKat Print框架

chris發表於2014-06-24

你有沒有想過給你的Android應用新增列印的功能?

在Android4.4之前,Android上沒有專門為列印提供的API,如果要實現列印的話,只能依賴第三方的解決方案,或者自己實現SMB/CIFS這樣的協議,用WIFI、藍芽或者USB直接和印表機通訊。而我們絕大多數人也不會想去直接和印表機通訊,一般都是依靠已經存在的方案,這也是最好的選擇了。其實,這就是Android新增的功能,可以讓列印功能更加簡單和可靠。

雲列印技術

Google Cloud Print Service最先是在2010年4月對外發布的,GCP是一個基於web的印表機,也是一個可以提供列印功能的管理系統,它能讓任何聯網裝置都可以使用GCP服務來連結任何一臺印表機。使用者可以為GCP服務新增任何一臺印表機,設定是很老式印表機、非雲端連線的印表機也是可以的,只需要保證印表機與連線的電腦在web上是共享的,並且裝有Google的Chrome。據作者所說,使用GCP是讓Android4.4以下的系統支援列印功能的最簡單方式。GCP也是我們最希望在Android4.4以上裝置上見到的新功能,所以可以開始學習了。點選這裡檢視資料。

KitKat之前的列印技術

Google雲列印技術給開發者提供了一系列API,只要開發者擁有Google認證賬號就可以提交列印任務和接收列印任務了。可以從這裡下載Google雲列印相關的開發資料https://developers.google.com/cloud-print/。本文不會涉及任何實現的細節,因為它有點長,而且幫助不大。還有一點是,使用者必須正確設定GCP賬號,並和印表機繫結,下面將要介紹兩種實現方法。

Google雲列印APP

Paulo Fernandes是第一個在APP中使用雲列印服務的人,它的Cloud Print應用是第一款使用GCP API來為Android裝置提供列印服務的APP。兩年後,也就是2013年六月的時候,Google退出了它自己的版本,叫做Google Cloud Print。我會用Google Cloud Print作為例子進行講解,因為它更流行一些,不過我自己也覺得大多數雲列印類APP都差不多。首先,我們需要使用PackageManager這個類來保證Android裝置上已經執行了Google Cloud Print服務,可以使用這個函式:

如果裝置上裝了Google Cloud Print服務的話,我們就可以使用一個Intent來開始列印了:

或者,還可以使用webview呼叫Google Cloud Print的web介面,這裡省略了這部分,這裡有一個例子,感興趣的可以看看完整示例.

在KitKat系統中進行列印

有了這個列印的API,Android上列印就變得更簡單、更可靠了。這是它的API的更新列表,以包的形式組織:

Android.support.v4.print

  • PrintHelper – bitmap列印佇列工具類。

Android.print

  • PrintDocumentAdapter – 提供自定義列印文件的基礎類。
  • PrintManager – 訪問列印佇列,並提供PrintDocumentAdapter類支援。

Android.print.pdf

  • PrintedPdfDocument – 基於特定PrintAttributeshelper建立PDF。

Android.webkit

  • WebView.createPrintDocumentAdapter – 為WebView列印內容建立PrintDocumentAdapter。

Android.printservice

  • 實現自定義PrintService的容器類。

我們先來看看Android.printservice,這個包裡面有與實現自己的列印服務相關的類,Print Service抽象出了與真實印表機(或者其它中間部件如GCP)之間的通訊,Google Cloud Print APP就在KitKat上實現了這個服務,所以就可以在GCP上建立列印任務了。關於Print Service的具體實現超出了本文的範圍,不過可以關注一下PrintService,它還是挺實用的,它是實現列印所必須的一個類,還有其它需要的相關類稍後就介紹。(需要注意的是:大多數KitKat裝置中預裝了Google Cloud Print,Chrome,Drive,Gallery還有Quickoffice的,都會提供列印的服務)

接下來要說的是PrintHelper,它也在Android.support.v4.print包下,你可能會想,既然這個類放在Android的相容包裡,那麼就可以在老版本的Android上使用列印的功能了。但是很不幸的是,事實不是這樣的,PrintHelper這個類有一個靜態方法systemSupportsPrint(),從本人進行的測試來看,這個方法只有在KitKat裝置中才會返回true。如果在systemSupportPrint()這個方法返回false的裝置上呼叫printBitmap()方法的話,會直接被忽略,不會發生任何事件。現在我們只需要瞭解為什麼PrintHelper這個類會包含在Android的相容包裡面,好像也沒有什麼用,至少目前還沒有什麼用處。

不管怎麼樣,PrintHelper這個類在KitKat中進行列印操作還是很實用的,它提供了簡單,直接的方式來列印圖片。

  • 可以指定圖片的縮放模式,FILT或者FIT模式,FILT模式會用給出的圖片填充整個區域,並保持整體比例不變,可能會有裁剪。FIT模式會水平填充或者垂直填充,這取決於文件或者圖片的尺寸,它也會保持整體的比例,但是不會裁剪,所以可能會出現空白區域,除非圖片的比例和要列印的文件的比例正好合適。
  • 可以指定顏色模式,COLOR或者MONOCHROME。

還有一個很實用的新增方法叫createPrintDocumentAdapter(),為webview準備的。這個方法會和PrintManager一起使用,讓列印webview的內容更加簡單。

在列印webview的內容時,還需要注意的是:

  • 使用者不能指定列印的頁面範圍,所以只能列印整個文件。
  • PrintDocumentAdapter在被Webview建立的時候,只能提供當前載入的內容,如果文件沒載入完畢,或者中途又載入了別的文件,那麼可能會導致不可預料的結果,或者PrintDocumentAdapter會載入失敗。
  • 一個webview例項一次只能處理一個列印任務。

PrintManager這個類只有兩個公開的方法:getPrintJobs()和print()方法。getPrintJobs()方法會返回一個PrintJob型別的列表,這些PrintJob物件由應用呼叫。PrintJob物件在檢測狀態或者在取消或者重啟列印任務的時候很有用。在列印的時候會建立一個PrintJob物件(帶有標題,PrintDocumentAdapter和PrintAttributes),其中PrintAttributes可以讓你指定一種顏色模式,媒體尺寸,邊距還有解析度,還有要特別注意這些屬性的操作都是由PrintService操作的,使用者只是把任務提交而已。而且很有可能很多屬性與對應的服務是沒有關係的,或者是會被直接忽略掉的。一個簡單的例子就是在選擇“save as PDF”的時候,就會忽略掉顏色模式這個屬性。

最後要看的這個類叫PrintDocumentAdapter。這個類是一個基礎類,繼承它可以建立自定義的佈局和內容。儘管是可以用PrintHelper和Bitmap類來輕鬆對繪製的內容進行列印,但是PrintDocumentAdapter在佈局和屬性上更加靈活,在實現PrintDocumentAdapter的時候,有兩個可選的方法和兩個必須的方法,可選的方法是onStart()onFinish(),在分配和釋放資源的時候會需要這兩個方法。首先要看的一個必須的方法叫onLayout(),在PrintAttribute改變的時候就會呼叫這個方法,這個方法的主要目的就是為了建立PrintDocumentInfo物件,用於描述所列印的內容,和呼叫LayoutResultCallback物件裡的一個方法(有三個方法)。這也是建立PrintedPdfDocument物件最好的地方,所以就可以往裡面傳遞相應的列印屬性。

另外一個必須的方法叫onWrite(),這個方法在需要使用檔案描述符修改PDF檔案的時候,就會呼叫,特別要注意的是這個方法(PrintDocumentAdapter的方法也一樣)是在主執行緒呼叫的;在這裡提出,因為此方法最好是在後臺執行,因為考慮到我們會做一些檔案IO操作。這個方法的主要目的就是往PDF裡面寫內容,把PDF內容寫到檔案裡,然後呼叫對應的回撥方法。

總的來說,Android新增的列印框架也沒有加了很多新功能,但是它確實讓APP能夠更簡單、可靠地進行列印操作,大多數APP都提供了列印服務,而且很多都預裝在了KitKat裝置中。

相關文章