45

我们需要一台可以通过蓝牙或 wifi 连接到安卓手机的便携式打印机(手持式,这很重要)。

我目前所知道的:

  • 这次没有适用于 Android 的标准打印 SDK
  • 有一个名为iPrint SDK的非官方SDK 。你们有没有人通过wifi或蓝牙尝试过?它有效吗?
  • Printershare还声称以编程方式可用。我可以为每部电话支付 5 美元的一次性费用。它有很多支持的格式。您是否尝试过使用任何手持设备?我向他们询问了支持的蓝牙打印机列表(因为它有一个菜单项“搜索 BT 打印机”),但他们没有回答。

在已经问过的问题上我需要知道的:

  • 你如何从你的安卓应用程序打印?
  • 您使用哪种打印机?
  • 是否计划在标准 android SDK 中包含打印功能?路线图是什么?它现在是 Beta 版还是什么的?
  • 如果我们以某种方式(我不这么认为)构建自己的蓝牙打印解决方案,您能否推荐标准和协议来检查和学习?
4

7 回答 7

19

Android 4.4开始,您可以通过 wifi 将文档从设备打印到硬件打印机。

Android 应用程序现在可以通过 Wi-Fi 或云托管服务(例如 Google Cloud Print)打印任何类型的内容。在支持打印的应用程序中,用户可以发现可用的打印机、更改纸张尺寸、选择要打印的特定页面,以及打印几乎任何类型的文档、图像或文件。

如何开始打印过程的简要示例:

private void doPrint() {
    PrintManager printManager = (PrintManager) getActivity().getSystemService(Context.PRINT_SERVICE);
    printManager.print("My document", new CustomPrintDocumentAdapter(getActivity()), null);
}

其中 CustomPrintDocumentAdapter 扩展PrintDocumentAdapter

有关更多信息,请访问Android 开发人员

于 2013-12-08T00:06:55.820 回答
15

目前无法在 Android 上通过蓝牙进行打印(据我所知),因为 Android 不支持蓝牙“配置文件”,例如 BPP(基本打印配置文件)、HCRP(硬拷贝替换配置文件)、BIP(基本成像配置文件)等,这是蓝牙打印使用的常用配置文件。参考。是要了解打印 BT 配置文件。

目前,Android 支持 OPP(Object Push Profile),用于通过蓝牙发送文件。

要在 Android 的蓝牙堆栈中实现打印蓝牙配置文件,您可以参考Sybase-iAnywhere-Blue-SDK-for-Android,它提供了一个 SDK 以将此功能添加到 Android 上现有的 BT 堆栈实现。

对于 Wifi 打印,市场上有许多应用程序可让您从 Android 手机打印各种文档和图像。请参阅PrinterShare了解此类应用程序。对于 Wifi 打印,您可以使用任何可以通过以太网 (LAN) 连接的打印机。

还可以查看启用了“谷歌云打印”的打印机,它使用云打印到连接在世界任何地方的支持此协议的打印机。这在市场上是相当新的,但在未来几年肯定会受到关注。在此处查看云打印应用程序。和常见问题解答在这里

希望这有助于从您的列表中删除一些问题。

于 2011-05-27T04:57:14.197 回答
8

抱歉,我不了解使用蓝牙设备进行打印。但是,我对使用 wifi 进行打印进行了一些研究,并将该代码发布在 GitHub 中,如果需要,您可以参考。Android-wifi-print - GitHub

这是该原型的流程。

  1. 检查连接性。
  2. 如果在 WiFi 中连接.. 正在存储该 WiFi 配置。
  3. 现在检查我是否已经有打印机的信息(WiFi 打印机的 WiFi 配置)是否可用。如果可用,我将扫描并获取 WiFi 扫描结果列表并连接到其他列表。它将显示 WiFi 列表并单击该列表,用户将连接到打印机并存储该 WiFi 配置以供将来的打印作业使用。
  4. 打印作业完成后,我将连接到之前的 WiFi 或移动数据连接。
  5. 现在回到第二步。
  6. 如果用户在移动数据中连接,我只是启用 WiFi 并执行第 3 步。
  7. 打印作业完成后,我只是禁用了 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) {

    }

}

在以下链接的帮助下,我创建了这个。

如果你想打印你的文件,只需调用print(file)

如果要下载文件并打印,请调用downloadAndPrint(fileUrl, fileName)

于 2015-07-06T08:20:14.263 回答
7

我能够集成的唯一印刷是 Bixolon SPP-R200。他们有一个不错的 SDK 可用并且很容易找到。我正在寻找 8 1/2 x 11 的蓝牙功能,但现在类似的 sdk 似乎是一个很高的要求

于 2011-02-03T18:06:25.043 回答
3

Star Micronics 有一个用于通过蓝牙(以及 wifi/以太网和 USB)进行 Android 打印的 SDK。您可以在此处下载:http: //www.starmicronics.com/support/SDKDocumentation.aspx

如上所述,此时您无法进行本机打印,因此您可以选择特定的打印机 API 或 3rd 方打印应用程序。

根据我的经验,最好使用 API 而不是外部应用程序。最大的原因是您可以完全控制打印机的行为。如果 API 是智能构建的,则很容易实现。使用 3rd 方应用程序会受到限制,因为您无法按照自己的方式自定义打印输出。

我链接到的 Star SDK 有一个非常棒的示例应用程序,可让您测试和自定义许多打印机功能以查看它们的运行情况。每个函数都记录在源代码中。命令及其参数也可在应用程序本身中作为快速屏幕参考,这很方便。最重要的是,它有据可查。

如果您选择这种方式,您可以将纯文本连同命令一起发送到打印机。API 处理将数据转换为打印机可以理解的内容。

于 2012-05-25T08:03:07.477 回答
2

还有另一个用于 Android 的打印 SDK,称为 APF。它基于 CUPS,因此支持多达数千台打印机。网站:isb-vietnam.com

于 2012-01-09T08:26:11.823 回答
2

Zebra Technologies 还提供适用于 Android 的 SDK。我已经尝试过他们的 SDK 和 Bixolon 的(通过写信给 techsupp@bixolon.de 得到)。两者都可以正常工作,但如果您更喜欢使用页面描述语言来定义您的文档,您最好使用 Zebra 打印机。

于 2012-06-25T22:37:48.113 回答