适用于Android的蓝牙和WIFI打印

我们需要一台可以通过蓝牙或wifi连接到Android手机的便携式打印机(手持设备,这很重要)。 我目前所知道的: 这次没有适用于Android的标准打印SDK 有一个名为iPrint SDK的非官方SDK。有没有人通过wifi或蓝牙试过?它有用吗? Printershare还声称可以通过程序化方式获得。我可以为每部手机支付5美元的一次性费用。它有很多支持的格式。你有没有尝试过任何手持设备?我向他们询问了支持的蓝牙打印机列表(因为它有一个菜单项“搜索BT打印机”),但他们没有回答。 我已经问过上面需要知道的事情: 你如何从你的Android应用程序打印? 你用的是什么类型的打印机? 是否计划在标准的Android SDK中包含打印?什么是路线图?它现在可用作Beta还是其他什么? 如果我们以某种方式(我不这么认为)通过蓝牙构建自己的打印解决方案,您能推荐标准和协议来检查和学习吗?     
已邀请:
从Android 4.4开始,您可以通过wifi将文档从设备打印到硬件打印机。   Android应用现在可以通过Wi-Fi或云托管服务(如Google云打印)打印任何类型的内容。在支持打印的应用程序中,用户可以发现可用的打印机,更改纸张大小,选择要打印的特定页面,以及打印几乎任何类型的文档,图像或文件。 如何开始打印过程的简短示例:
private void doPrint() {
    PrintManager printManager = (PrintManager) getActivity().getSystemService(Context.PRINT_SERVICE);
    printManager.print("My document", new CustomPrintDocumentAdapter(getActivity()), null);
}
其中CustomPrintDocumentAdapter扩展PrintDocumentAdapter。 Android开发者可以获得更多信息。     
目前无法在Android上通过蓝牙打印(据我所知),因为Android不支持蓝牙'配置文件',例如BPP(基本打印配置文件),HCRP(硬拷贝替换配置文件),BIP(基本成像配置文件)等等,这是与蓝牙打印一起使用的常用配置文件。 参考。这可以了解打印BT配置文件。 目前,Android支持OPP(对象推送配置文件),用于通过蓝牙发送文件。 要在Android蓝牙堆栈中实现打印蓝牙配置文件,您可以参考Sybase-iAnywhere-Blue-SDK-for-Android,它提供了一个SDK,可将此功能添加到Android上现有的BT堆栈实现中。 对于Wifi打印,市场上有许多应用程序允许您从Android手机打印各种文档和图像。有关此类应用,请参阅PrinterShare。对于Wifi打印,您可以使用可以通过以太网(LAN)连接的任何打印机。 另外,请查看启用了“Google Cloud Print”的打印机,该打印机使用云打印到世界上任何位置连接的打印机,并支持此协议。这在市场上是相当新的,但在未来几年肯定会有所吸引力。在这里查看云打印应用程序。和常见问题这里。 希望这有助于从您的列表中删除一些问题。     
对不起,我不知道使用蓝牙设备打印.. 但是,我做了一些关于使用wifi进行打印的研究,并在GitHub中发布了该代码,如果需要,可以参考.. Android-wifi-print - GitHub 这是该原型的流程。 检查连接。 如果连接在WiFi ..我正在存储该WiFi配置。 现在检查我是否已经拥有打印机的信息(WiFi打印机的WiFi配置)是否可用。如果可用,我将扫描并获取WiFi ScanResults的列表并连接到其他..它将显示WiFi列表并单击它,用户将连接到打印机并存储该WiFi配置以用于将来的打印作业。 打印作业完成后,我将连接到之前的WiFi或移动数据连接。 现在回到第2步。 如果用户在移动数据中连接,我只是启用WiFi并执行第3步。 打印作业完成后,我只是禁用WiFi。这样,我们将连接回移动数据连接。 (那是android的默认值)。 下面的课程将负责该原型中的所有打印作业。 PrintUtility.class
public class PrintUtility implements Observer {

    private static final int TIME_OUT = 10000;
    private static final int CONNECTION_TIME_OUT = 5000;

    private Activity mActivity;
    private Fragment mFragment = null;

    private WifiConfiguration mPrinterConfiguration;
    private WifiConfiguration mOldWifiConfiguration;
    private WifiManager mWifiManager;
    private WifiScanner mWifiScanner;
    private List<ScanResult> mScanResults = new ArrayList<ScanResult>();

    private PrintManager mPrintManager;
    private List<PrintJob> mPrintJobs;
    private PrintJob mCurrentPrintJob;

    private File pdfFile;
    private String externalStorageDirectory;

    private Handler mPrintStartHandler = new Handler();
    private Handler mPrintCompleteHandler = new Handler();
    private Handler mWifiConnectHandler = new Handler();
    private String connectionInfo;

    private boolean isMobileDataConnection = false;

    private PrintCompleteService mPrintCompleteService;

    //    Observer pattern
    private Observable mObservable;


    public PrintUtility(Activity mActivity, WifiManager mWifiManager, WifiScanner mWifiScanner) {
        this.mActivity = mActivity;
        this.mWifiManager = mWifiManager;
        this.mWifiScanner = mWifiScanner;
        mPrintCompleteService = (PrintCompleteService) mActivity;
        mObservable = ObservableSingleton.getInstance();
        mObservable.attach(this);
    }

    public PrintUtility(Activity mActivity, Fragment mFragment, WifiManager mWifiManager, WifiScanner mWifiScanner) {
        this.mActivity = mActivity;
        this.mFragment = mFragment;
        this.mWifiManager = mWifiManager;
        this.mWifiScanner = mWifiScanner;
        mPrintCompleteService = (PrintCompleteService) mFragment;
        mObservable = ObservableSingleton.getInstance();
        mObservable.attach(this);
    }

    public void downloadAndPrint(String fileUrl, final String fileName) {

        new FileDownloader(mActivity, fileUrl, fileName) {
            @Override
            protected void onPostExecute(Boolean result) {

                if (!result) {
                    mObservable.notifyObserver(true);
                } else {

                    // print flow will come here.

                    try {
                        externalStorageDirectory = Environment.getExternalStorageDirectory().toString();
                        File folder = new File(externalStorageDirectory, Constants.CONTROLLER_PDF_FOLDER);
                        pdfFile = new File(folder, fileName);
                    } catch (Exception e) {
                        mObservable.notifyObserver(true);
                        e.printStackTrace();
                    }

                    print(pdfFile);

                }

            }
        }.execute("");
    }

    public void print(final File pdfFile) {

        this.pdfFile = pdfFile;

        // check connectivity info -> mobile or wifi.
        connectionInfo = Util.connectionInfo(mActivity);

        if (connectionInfo.equalsIgnoreCase(Constants.CONTROLLER_MOBILE)) {
            // follow mobile flow.
            isMobileDataConnection = true;

            if (mWifiManager.isWifiEnabled() == false) {
                mWifiManager.setWifiEnabled(true);
            }

            mWifiManager.startScan();
            setScanResults(mWifiScanner.getScanResults());

            printerConfiguration();

        } else if (connectionInfo.equalsIgnoreCase(Constants.CONTROLLER_WIFI)) {
            // follow wifi flow..

            // this will get current wifiInfo and store it in shared preference.
            Util.storeCurrentWiFiConfiguration(mActivity);

            printerConfiguration();

        } else {
            mObservable.notifyObserver(true);
        }

    }

    private void printerConfiguration() {

        // check printer detail is available or not.
        mPrinterConfiguration = Util.getWifiConfiguration(mActivity, Constants.CONTROLLER_PRINTER);

        if (mPrinterConfiguration == null) {
            // printer configuration is not available.
            // display list of wifi available in an activity

            showWifiListActivity(Constants.REQUEST_CODE_PRINTER);

        } else {
            // get list of wifi available. if printer configuration available then connect it.
            // else.. show list of available wifi nearby.

            boolean isPrinterAvailable = false;

            // scans nearby wifi..
            mWifiManager.startScan();
            setScanResults(mWifiScanner.getScanResults());


            // checks this wifi in scan result list..
            for (int i = 0; i < mScanResults.size(); i++) {
                if (mPrinterConfiguration.SSID.equals(""" + mScanResults.get(i).SSID + """)) {
                    isPrinterAvailable = true;
                    break;
                }
            }

            if (isPrinterAvailable) {

                // connect to printer wifi and show print settings dialog and continue with print flow.
                connectToWifi(mPrinterConfiguration);

                // prints document.
                doPrint();

            } else {
                showWifiListActivity(Constants.REQUEST_CODE_PRINTER);
            }

        }
    }

    private void showWifiListActivity(int requestCode) {
        Intent iWifi = new Intent(mActivity, WifiListActivity.class);
        mActivity.startActivityForResult(iWifi, requestCode);
    }

    private void connectToWifi(WifiConfiguration mWifiConfiguration) {
        mWifiManager.enableNetwork(mWifiConfiguration.networkId, true);
    }

    public void doPrint() {

        try {
            // it is taking some time to connect to printer.. so i used handler.. and waiting for its status.
            mPrintStartHandler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    mPrintStartHandler.postDelayed(this, TIME_OUT);

                    if (mPrinterConfiguration.status == WifiConfiguration.Status.CURRENT) {
                        if (mWifiManager.getConnectionInfo().getSupplicantState() == SupplicantState.COMPLETED) {

                            if (Util.computePDFPageCount(pdfFile) > 0) {
                                printDocument(pdfFile);
                            } else {

                                AlertDialog.Builder alert = new AlertDialog.Builder(mActivity);

                                alert.setMessage("Can't print, Page count is zero.");

                                alert.setNeutralButton("OK", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int i) {
                                        dialog.dismiss();
                                        switchConnection();
                                    }
                                });

                                alert.show();
                            }
                        }
                        mPrintStartHandler.removeCallbacksAndMessages(null);
                    } else {
                        Toast.makeText(mActivity, "Failed to connect to printer!.", Toast.LENGTH_LONG).show();
                        switchConnection();
                        mPrintStartHandler.removeCallbacksAndMessages(null);
                    }
                }
            }, TIME_OUT);
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(mActivity, "Failed to connect to printer!.", Toast.LENGTH_LONG).show();
            switchConnection();
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void printDocument(File pdfFile) {

        mPrintManager = (PrintManager) mActivity.getSystemService(Context.PRINT_SERVICE);

        String jobName = mActivity.getResources().getString(R.string.app_name) + " Document";

        mCurrentPrintJob = mPrintManager.print(jobName, new PrintServicesAdapter(mActivity, mFragment, pdfFile), null);
    }


    @TargetApi(Build.VERSION_CODES.KITKAT)
    public void completePrintJob() {
        mPrintJobs = mPrintManager.getPrintJobs();

        mPrintCompleteHandler.postDelayed(new Runnable() {
            @Override
            public void run() {

                mPrintCompleteHandler.postDelayed(this, CONNECTION_TIME_OUT);

                if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_COMPLETED) {

                    // remove that PrintJob from PrintManager.
                    for (int i = 0; i < mPrintJobs.size(); i++) {
                        if (mPrintJobs.get(i).getId() == mCurrentPrintJob.getId()) {
                            mPrintJobs.remove(i);
                        }
                    }

                    // switching back to previous connection..
                    switchConnection();

                    // stops handler..
                    mPrintCompleteHandler.removeCallbacksAndMessages(null);
                } else if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_FAILED) {
                    switchConnection();
                    Toast.makeText(mActivity, "Print Failed!", Toast.LENGTH_LONG).show();
                    mPrintCompleteHandler.removeCallbacksAndMessages(null);
                } else if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_CANCELED) {
                    switchConnection();
                    Toast.makeText(mActivity, "Print Cancelled!", Toast.LENGTH_LONG).show();
                    mPrintCompleteHandler.removeCallbacksAndMessages(null);
                }

            }
        }, CONNECTION_TIME_OUT);
    }

    public void switchConnection() {
        try {
            if (!isMobileDataConnection) {

                mOldWifiConfiguration = Util.getWifiConfiguration(mActivity, Constants.CONTROLLER_WIFI);

                // get list of wifi available. if wifi configuration available then connect it.
                // else.. show list of available wifi nearby.
                boolean isWifiAvailable = false;

                // scans nearby wifi.
                mWifiManager.startScan();
                setScanResults(mWifiScanner.getScanResults());

                // checks this wifi in scan result list.
                for (int i = 0; i < mScanResults.size(); i++) {
                    if (mOldWifiConfiguration.SSID.equals(""" + mScanResults.get(i).SSID + """)) {
                        isWifiAvailable = true;
                        break;
                    }
                }

                if (isWifiAvailable) {

                    // connect to printer wifi and show print settings dialog and continue with print flow.
                    connectToWifi(mOldWifiConfiguration);

                    mWifiConnectHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mWifiConnectHandler.postDelayed(this, TIME_OUT);
                            if (mOldWifiConfiguration.status == WifiConfiguration.Status.CURRENT) {
                                if (mWifiManager.getConnectionInfo().getSupplicantState() == SupplicantState.COMPLETED) {

                                    try {
                                        mObservable.notifyObserver(true);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }

                                    mWifiConnectHandler.removeCallbacksAndMessages(null);
                                }
                            }
                        }
                    }, TIME_OUT);

                } else {
                    showWifiListActivity(Constants.REQUEST_CODE_WIFI);
                }
            } else {
                mWifiManager.setWifiEnabled(false);
                mObservable.notifyObserver(true);
            }
        } catch (Exception e) {
            mObservable.notifyObserver(true);
            e.printStackTrace();
        }
    }

    public void getPrinterConfigAndPrint() {
        mPrinterConfiguration = Util.getWifiConfiguration(mActivity, Constants.CONTROLLER_PRINTER);
        doPrint();
    }

    public void setScanResults(List<ScanResult> scanResults) {
        this.mScanResults = scanResults;
    }

    public void onPrintCancelled() {
        switchConnection();
    }

    @Override
    public void update() {
        mObservable.detach(this);
    }

    @Override
    public void updateObserver(boolean bool) {

    }

    @Override
    public void updateObserverProgress(int percentage) {

    }

}
在以下链接的帮助下,我创建了这个。 用于学习打印作业的链接 用于学习WiFi配置和交换的链接 如果要打印文件,只需调用print(文件) 如果要下载文件并打印出来, 调用downloadAndPrint(fileUrl,fileName)     
我能够整合的唯一印刷是Bixolon SPP-R200。他们有一个不错的SDK,很容易找到。我正在寻找8 1/2 x 11蓝牙功能但是这样的sdk似乎是一个相当高的订单现在     
Star Micronics有一个通过蓝牙(以及wifi /以太网和USB)进行Android打印的SDK。您可以在此处下载:http://www.starmicronics.com/support/SDKDocumentation.aspx。 如上所述,您无法在此时进行本地打印,因此您的选项可以是特定的打印机API或第三方打印应用程序。 根据我的经验,最好使用API​​而不是外部应用程序。最大的原因是您可以完全控制打印机行为。如果API是智能构建的,那么很容易实现。使用第三方应用程序是有限制的,因为您无法以您希望的方式自定义打印输出。 我链接到你的Star SDK有一个非常好的示例应用程序,它允许您测试和自定义许多打印机功能,以查看它们的运行情况。每个函数都记录在源代码中。这些命令及其参数也可以在应用程序本身中作为快速屏幕参考使用,这很方便。最重要的是,它有很好的记录。 如果选择这种方式,则可以将明文与命令一起发送到打印机。 API处理将数据转换为打印机可以理解的内容。     
还有一个名为APF的Android打印SDK。它基于CUPS,因此支持数千台打印机。网站:isb-vietnam.com     
Zebra Technologies还提供适用于Android的SDK。我已经尝试了他们的SDK和Bixolon(通过写信到techsupp@bixolon.de得到它)。两者都工作正常,但如果您更喜欢使用页面描述语言来定义文档,那么最好使用Zebra打印机。     

要回复问题请先登录注册