最近專案需要用到藍芽列印,百度了很多資料,關於安卓移動列印的文章都不是很詳細。要知道自己去寫一個藍芽列印模組那可是一個比較大的工作量了,而且還需要對市面上的印表機進行相容。這個我引用一篇文章大家看下:
一、Android客戶端列印技術現狀
雲列印
在Android KitKat之前,Google推出雲列印,使用者將需要列印的資料上傳到伺服器並填寫好聯絡資訊,列印好的圖片郵寄給使用者。
這是一種商業模式而非技術手段。也就是說在Android KitKat之前,Google一直沒有推出Android列印的技術方案。除了Google推出的雲列印方案,還存在很多第三方公司,也提供類似的方案(參考:2)。
列印框架
KitKat釋出,Google推出了列印框架。該框架作為需要使用列印服務的應用於實現列印服務的應用之間的介面,通過該框架方便了開發者對列印功能的使用。其中,需要使用列印服務的應用使用列印框架API申請服務,具體的列印服務由印表機原始裝置生產生提供。本質上,該框架方便了應用列印功能的使用,但實際上列印中最為關鍵的列印資料流的建立仍然是印表機生產商提供的APK來完成。(參考:3)
第三方
除了各大印表機生產廠商提供的列印APK,還有部分第三方也提供具有列印功能的應用,比如 PrinterShare這款應用。該應用的實現原理不明,猜測可能是其獲取到了各個廠商的PDL的支援情況,並且擁有特定PDL的開發參考資料。
市場上的產品
以金山公司的 WPS為例,該應用支援常用辦公檔案的列印,列印提供兩種選項:第一,使用系統的列印服務,即之前提到的KitKat之後的列印框架;第二,生成.ps檔案。需要說明的一點是,該檔案的內容是PostScript,根據前面的描述可知,該檔案並不被所有印表機支援。所以,該應用的做法是,通過使用列印框架提供列印功能,同時提供對部分印表機的支援。此外,通過搜尋可以發現,目前市場上關於列印類的應用非常少。(參考:4)
二、可行方案
通過前面的瞭解,確定兩種方案
- 方式一:應用操作 excel 檔案填入資料,列印功能由第三方應用實現
- 方式二:使用PDL實現列印
方式一
- 應用更新並下載列印模板(.xsl檔案)
- 應用通過第三方SDK操作模板檔案,將相應的資料填入
- 列印目標檔案生成完成後,使用者通過第三方應用實施列印
第三方應用:
1)廠商提供的APK,支援某些型號的印表機(支援範圍不廣)
2)第三方提供的APK,比如PrintShare(支援的範圍較廣,參考:5)
關於印表機的選擇,支援的印表機要求:
a. 便於攜帶
b. 外掛支援
c. 價格在一定範圍
方式二
- 同方式一,但是下載的檔案是.txt檔案
- 應用將模板txt與資料拼合
- 應用生成列印資料流通過藍芽發往印表機
比較
列印方式 | 列印效果 | 開發和維護難度 | 應用的使用難度 |
---|---|---|---|
方式一 | 好 | 簡單 | 比較復 |
方式二 | 不好 | 複雜 | 低 |
列印效果方面,方式一的列印效果幾乎與通過PC列印效果一直,方式二的列印效果存在字型模糊、樣式不能被完全體現等問題。
技術實現方面,方式一可利用現有的比價成熟的excel檔案操作SDK,方式二需要處理格式轉換、檔案拼接以及列印資料生成等問題。
實際選用:方式二。
三、HP PCL 3 列印語言
具體內容參考手冊:PCL3_developers_guide.pdf
下面簡要介紹一下該語言的基礎知識
- 改語言由指令構成,類似組合語言,每種功能通過特定的指令實現。比如,字號的設定通過某條指令實現
- 該指令存在多個版本,目標印表機使用的版本是 PCL 3 GUI,其是 PCL的第三版,相對 PCL 3對圖形列印有較好的支援,其語言指令是PCL 3的超集。
可以看到還是比較複雜的。今天我們就呼叫PrinterShare實現列印,列印工作交給它去做,我們把檔案傳給他就行,具體實現流程:
1、下載官方apk,不要去國內市場去下載,ps:我在國內市場上下載的apk包名跟官方不一樣(/ □ \)com.dynamixsoftware.printershareoaj,最新版是這個com.dynamixsoftware.printershare
2、反編譯apk,這個不用說了大家都會;
3、檢視清單檔案我們需要關注幾點:
1)、包名
2)、相關activity這裡有很多列印模式:圖片、pdf、word、doc、xls、ppt等等,我列印的是txt文字,選擇的是這個activity
4、擼程式碼。。。
1)、把apk安裝包copy到assets目錄下
2)、安裝apk,檢測是否已經安裝:
public static boolean isInstallApp(Context context, String packageName) {
return !RxDataUtils.isNullString(packageName) && RxIntentUtils.getLaunchAppIntent(context, packageName) != null;
}複製程式碼
如果已經安裝就去列印,這裡就用到了我們上面解析清單檔案的內容了,設定包名、動作傳遞、檔案型別、設定資料:
ComponentName comp = new ComponentName("com.dynamixsoftware.printershare","com.dynamixsoftware.printershare.ActivityPrintDocuments");
Intent intent = new Intent();
intent.setComponent(comp);
intent.setAction("android.intent.action.VIEW");
intent.setType("text/plain");
intent.setData(Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/test.txt"));
startActivity(intent);複製程式碼
ps:這裡我直接在sd卡跟目錄放置了一個test文字。
關於ComponentName大家可以查下資料,可以開啟另一個應用的元件。
如果沒有安裝就把檔案拷貝出來再安裝:
從assets裡面copy檔案:
public File getAssetFileToCacheDir( String fileName) {
try {
File cacheDir = FileUtil.getCacheDir(MyApp.getApplictaion());
final String cachePath = cacheDir.getAbsolutePath()+ File.separator + fileName;
InputStream is = MyApp.getApplictaion().getAssets().open(fileName);
File file = new File(cachePath);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] temp = new byte[1024];
int i = 0;
while ((i = is.read(temp)) > 0) {
fos.write(temp, 0, i);
}
fos.close();
is.close();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mRxDialogLoading.cancel();
}
});
return file;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}複製程式碼
安裝:
public static void InstallAPK(Context context, String APK_PATH) {//提示安裝APK
Intent i = new Intent(Intent.ACTION_VIEW);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setDataAndType(Uri.parse("file://" + APK_PATH), "application/vnd.android.package-archive");
context.startActivity(i);
}複製程式碼
到此整個呼叫PrinterShare列印就完成了我們看下效果:
點選列印提示安裝apk:
安裝成功,再點選“列印”按鈕
繼續,這個時候提示需要載入渲染庫,點選是,ps:慢慢等它載入完~~~
最後預覽圖:
test原文字是這樣的:
吐槽,PrinterShare的UI是真的醜~~~~~
分割線--------------------------------------------------------------------------------------------------------------------
更新部分:
上面部分是列印txt文字,然而實際需求肯定不是列印txt,列印txt文字排版很不好字型也不好控制,而且特殊字元無法顯示出來,一般都是列印pdf、word、html。。。
我實際專案需求是列印一個罰單,還算簡單,有的是列印電子賬單。。。一開始想用itext把文字內容轉pdf去列印,ps:itext功能真的是很強大,pc上表現很強,有興趣的朋友可以去研究研究,分5和7,一個社群版本一個商業版本,地址~~~,可是後來想想首先(1)、加jar包,apk體積增大,(2)效能,安卓平臺和pc平臺這個都懂的,資源緊缺啊!java版本的在大部分是在pc上的專案,雖然國外有大牛把專案移植到安卓上,但是直接拿到安卓上去用還是有很多坑。。。(3)結合自身專案需求,沒必要~~~
好了進入正題
1、新建一個html放到assets目錄下(或者sd卡目錄下在或者伺服器上也可以)
這個是我需要列印的內容,暫時就這樣,比較簡單不花俏,後面還需要加個印章~~~大致效果就是這樣。
ps:為了不打擾前端大佬我自己動手寫的,,我不會前端不會前端啊!~~~~~這個可以讓前端根據列印內容寫個漂亮的html。
2、找到我們上面的清單檔案這次我們使用的是ActivityWeb
3、擼程式碼
注意:這裡跟我們上面列印txt不一樣了,activity元件、Type型別、Data都不一樣
URI轉換需要注意,前面需要加個“file:///”,一開始我就寫了個本地sd卡路徑,怎麼都顯示不了資料,後來發現ActivityWeb是先通過WebView載入網頁顯示再去列印的,WebView載入網頁和本地html都知道吧,這裡就不詳說了。。。
ComponentName comp = new ComponentName("com.dynamixsoftware.printershare","com.dynamixsoftware.printershare.ActivityWeb");
Intent intent = new Intent();
intent.setComponent(comp);
intent.setAction("android.intent.action.VIEW");
intent.setType("text/html");
intent.setData(Uri.parse("file:///"+Environment.getExternalStorageDirectory().getPath()+"/test2.html"));
startActivity(intent);複製程式碼
ps:這裡我直接在sd卡目錄放了個test2.html,實際需求場景還需要進一步考慮~~~~~反正先完成功能就ok~~~~~如果html是放在伺服器那麼就傳一個列印html的地址。
好了,看一下效果吧:
點選"列印"跳轉到預覽
OK,PrinterShare功能是不是很強大?文字、pdf、doc、word、網頁、表格、圖片等等都可以進行列印,大家可以自行研究其他功能~~~匹配好它清單檔案的過濾條件實現無線列印功能。