Android的蓝牙和WIFI打印
我们需要一台可以通过蓝牙或WiFi连接到android手机的便携式打印机(手持式,重要的)。
我目前所知道的:
- 这次没有可用于Android的标准打印SDK
- 有一个非官方的SDK叫做iPrint SDK 。 你有没有尝试过通过WiFi或蓝牙? 它工作吗?
- Printershare也声称可以通过程序获得 。 我可以每个电话支付一次性费用5美元。 它有很多支持的格式。 你用任何手持设备试过吗? 我问他们关于支持的蓝牙打印机列表(因为它有一个菜单项“searchBT打印机”),但他们没有回答。
上面已经提到的我需要知道的是:
- 你如何从你的Android应用程序打印?
- 你使用什么样的打印机?
- 计划在标准的android SDK中包含打印吗? 什么是路线图? 它现在是可用的Beta或者什么的?
- 如果我们以某种方式(我不这么认为)通过蓝牙构build自己的打印解决scheme,您能推荐标准和协议来检查和学习吗?
从Android 4.4开始,您可以通过WiFi将文档从设备打印到硬件打印机。
Android应用程序现在可以通过Wi-Fi或云托pipe服务(如Google Cloud Print)打印任何types的内容。 在支持打印的应用程序中,用户可以发现可用的打印机,更改纸张大小,select要打印的特定页面,以及几乎可以打印任何types的文档,图像或文件。
如何开始打印过程的简要示例:
private void doPrint() { PrintManager printManager = (PrintManager) getActivity().getSystemService(Context.PRINT_SERVICE); printManager.print("My document", new CustomPrintDocumentAdapter(getActivity()), null); }
CustomPrintDocumentAdapter扩展PrintDocumentAdapter 。
有关Android开发人员的更多信息。
由于Android不支持诸如BPP(基本打印configuration文件),HCRP(硬拷贝replaceconfiguration文件),BIP(基本成像configuration文件)之类的蓝牙“configuration文件”,因此根据我的知识,这是与蓝牙打印一起使用的常用configuration文件。 参考。 这要了解打印BTconfiguration文件。
目前,Android支持用于通过蓝牙发送文件的OPP(Object Push Profile)。
要在Bluetooth Stack for Android中实现打印蓝牙configuration文件,可以参考Sybase-iAnywhere-Blue-SDK-for-Android ,它提供了一个SDK,将此function添加到Android上的现有BT堆栈实现。
对于无线打印,市场上有许多应用程序,允许您从Android手机打印各种文件和图像。 看到一个这样的应用程序的PrinterShare 。 对于Wifi打印,您可以使用任何可以通过以太网(LAN)连接的打印机。
还可以查看启用了“Google云打印”function的打印机,该打印机使用云打印到支持此协议的世界上任何地方的打印机。 这在市场上是相当新的,但在未来几年肯定会有一些吸引力。 在这里查看云打印应用程序 。 和常见问题在这里 。
希望这有助于从列表中删除几个问题。
我唯一能够整合的打印机是Bixolon SPP-R200。 他们有一个体面的SDK可用,很容易find。 我正在寻找8 1/2 x 11蓝牙function,但是像这样的sdk似乎是一个相当高的订单
对不起,我没有关于使用蓝牙设备打印的知识..但是,我做了一些关于打印使用WiFi的研究,并张贴在GitHub的代码,您可以参考,如果需要.. Android的WiFi打印 – GitHub
这是原型的stream程。
- 检查连接性。
- 如果连接在WiFi ..我存储该WiFiconfiguration。
- 现在检查是否已经有打印机信息(WiFi打印机的WiFiconfiguration)是否可用。 如果可用的话,我将扫描并获取WiFi扫描结果列表,并连接到其他。它将显示WiFi列表并点击该列表,用户将连接到打印机并存储该WiFiconfiguration以用于将来的打印作业。
- 打印作业完成后,我将连接到以前的WiFi或移动数据连接。
- 现在回到第二步。
- 如果用户连接到移动数据,我只是启用WiFi和第三步。
- 打印作业完成后,我只是禁用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) { } }
借助以下链接,我创build了这个。
- 学习链接打印作业
- 学习WiFiconfiguration和切换的链接
如果你想打印你的文件只需打印(文件)
如果你想下载一个文件并打印,请调用downloadAndPrint(fileUrl,fileName)
Star Micronics有一个通过蓝牙进行Android打印的SDK(以及wifi / ethernet和USB)。 你可以在这里下载: http : //www.starmicronics.com/support/SDKDocumentation.aspx 。
如上所述,您目前无法在本机打印,因此您的选项可能是特定的打印机API或第三方打印应用程序。
根据我的经验,最好使用API而不是外部应用程序。 最大的原因是您可以完全控制打印机的行为。 如果API是智能构build的,则很容易实现。 使用第三方应用程序是有限的,因为您无法按照自己的意愿自定义您的打印输出。
我把你链接到的Star SDK有一个非常好的示例应用程序,它可以让你testing和定制很多打印机function,以便看到它们在运行。 每个函数都logging在源代码中。 这些命令及其参数也可以在应用程序本身作为快捷的屏幕参考,这是方便的。 最重要的是,这是有据可查的。
如果您select这种方式,则可以将纯文本与命令一起发送到打印机。 API处理将数据转换为打印机可以理解的内容。
另外还有一个名为APF的打印SDK。 它基于CUPS,因此可支持数千台打印机。 网站: isb-vietnam.com
Zebra Technologies还为Android提供了一个SDK 。 我已经尝试了他们的SDK和Bixolon(通过写给techsupp@bixolon.de)。 两者都可以正常工作,但如果您更喜欢使用页面描述语言来定义您的文档,则最好使用Zebra打印机。