安卓調用PrinterShare實現無線打印功能

 最近項目須要用到藍牙打印,百度了不少資料,關於安卓移動打印的文章都不是很詳細。要知道本身去寫一個藍牙打印模塊那但是一個比較大的工做量了,並且還須要對市面上的打印機進行兼容。這個我引用一篇文章你們看下:html

1、Android客戶端打印技術現狀

雲打印

在Android KitKat以前,Google推出雲打印,用戶將須要打印的數據上傳到服務器並填寫好聯繫信息,打印好的圖片郵寄給用戶。
這是一種商業模式而非技術手段。也就是說在Android KitKat以前,Google一直沒有推出Android打印的技術方案。除了Google推出的雲打印方案,還存在不少第三方公司,也提供相似的方案(參考:2)。前端

打印框架

KitKat發佈,Google推出了打印框架。該框架做爲須要使用打印服務的應用於實現打印服務的應用之間的接口,經過該框架方便了開發者對打印功能的使用。其中,須要使用打印服務的應用使用打印框架API申請服務,具體的打印服務由打印機原始設備生產生提供。本質上,該框架方便了應用打印功能的使用,但實際上打印中最爲關鍵的打印數據流的建立仍然是打印機生產商提供的APK來完成。(參考:3)java

第三方

除了各大打印機生產廠商提供的打印APK,還有部分第三方也提供具備打印功能的應用,好比 PrinterShare這款應用。該應用的實現原理不明,猜想多是其獲取到了各個廠商的PDL的支持狀況,而且擁有特定PDL的開發參考數據。android

市場上的產品

以金山公司的 WPS爲例,該應用支持經常使用辦公文件的打印,打印提供兩種選項:第一,使用系統的打印服務,即以前提到的KitKat以後的打印框架;第二,生成.ps文件。須要說明的一點是,該文件的內容是PostScript,根據前面的描述可知,該文件並不被全部打印機支持。因此,該應用的作法是,經過使用打印框架提供打印功能,同時提供對部分打印機的支持。此外,經過搜索能夠發現,目前市場上關於打印類的應用很是少。(參考:4)api

2、可行方案

經過前面的瞭解,肯定兩種方案bash

  • 方式一:應用操做 excel 文件填入數據,打印功能由第三方應用實現
  • 方式二:使用PDL實現打印

方式一

  1. 應用更新並下載打印模板(.xsl文件)
  2. 應用經過第三方SDK操做模板文件,將相應的數據填入
  3. 打印目標文件生成完成後,用戶經過第三方應用實施打印
    第三方應用:
    1)廠商提供的APK,支持某些型號的打印機(支持範圍不廣)
    2)第三方提供的APK,好比PrintShare(支持的範圍較廣,參考:5)
    關於打印機的選擇,支持的打印機要求:
    a. 便於攜帶
    b. 插件支持
    c. 價格在必定範圍

方式二

  1. 同方式一,可是下載的文件是.txt文件
  2. 應用將模板txt與數據拼合
  3. 應用生成打印數據流經過藍牙發往打印機

比較

打印方式 打印效果 開發和維護難度 應用的使用難度
方式一 簡單 比較復
方式二 很差 複雜

打印效果方面,方式一的打印效果幾乎與經過PC打印效果一直,方式二的打印效果存在字體模糊、樣式不能被徹底體現等問題。
技術實現方面,方式一可利用現有的比價成熟的excel文件操做SDK,方式二須要處理格式轉換、文件拼接以及打印數據生成等問題。服務器

實際選用:方式二。app

3、HP PCL 3 打印語言

具體內容參考手冊:PCL3_developers_guide.pdf框架

下面簡要介紹一下該語言的基礎知識ide

  1. 改語言由指令構成,相似彙編語言,每種功能經過特定的指令實現。好比,字號的設置經過某條指令實現
  2. 該指令存在多個版本,目標打印機使用的版本是 PCL 3 GUI,其是 PCL的第三版,相對 PCL 3對圖形打印有較好的支持,其語言指令是PCL 3的超集。

能夠看到仍是比較複雜的。今天咱們就調用PrinterShare實現打印,打印工做交給它去作,咱們把文件傳給他就行,具體實現流程:

一、下載官方apk,不要去國內市場去下載,ps:我在國內市場上下載的apk包名跟官方不同(/ □ \)com.dynamixsoftware.printershareoaj,最新版是這個com.dynamixsoftware.printershare

二、反編譯apk,這個不用說了你們都會;

三、查看清單文件咱們須要關注幾點:

    1)、包名


    2)、相關activity這裏有不少打印模式:圖片、pdf、word、doc、xls、ppt等等,我打印的是txt文本,選擇的是這個activity


四、擼代碼。。。

    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)結合自身項目需求,不必~~~

好了進入正題

一、新建一個html放到assets目錄下(或者sd卡目錄下在或者服務器上也能夠)


這個是我須要打印的內容,暫時就這樣,比較簡單不花俏,後面還須要加個印章~~~大體效果就是這樣。

ps:爲了避免打擾前端大佬我本身動手寫的,,我不會前端不會前端啊!~~~~~這個可讓前端根據打印內容寫個漂亮的html。

二、找到咱們上面的清單文件此次咱們使用的是ActivityWeb


三、擼代碼

注意:這裏跟咱們上面打印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、網頁、表格、圖片等等均可以進行打印,你們能夠自行研究其餘功能~~~匹配好它清單文件的過濾條件實現無線打印功能。

相關文章
相關標籤/搜索