我们需要一台可以通过蓝牙或wifi连接到Android手机的便携式打印机(手持设备,这很重要)。
答案 0 :(得分: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 Developers。
答案 1 :(得分:16)
目前无法在Android上通过蓝牙打印(据我所知),因为Android不支持蓝牙'配置文件',例如BPP(基本打印配置文件),HCRP(硬拷贝替换配置文件),BIP(基本打印)成像配置文件)等,这是与蓝牙打印一起使用的常见配置文件。 参考。 this了解打印BT配置文件。
目前,Android支持OPP(对象推送配置文件),用于通过蓝牙发送文件。
要在Android蓝牙堆栈中实现打印蓝牙配置文件,您可以参考Sybase-iAnywhere-Blue-SDK-for-Android,它提供了一个SDK,可以将此功能添加到Android上现有的BT堆栈实现中。
对于Wifi打印,市场上有许多应用程序允许您从Android手机打印各种文档和图像。有关此类应用,请参阅PrinterShare。对于Wifi打印,您可以使用可以通过以太网(LAN)连接的任何打印机。
另请查看启用了“Google Cloud Print”的打印机,该打印机使用云打印到世界上任何地方连接的打印机,并支持此协议。这在市场上是相当新的,但在未来几年肯定会有所吸引力。查看Cloud print app here。和faq here。
希望这有助于从您的列表中删除一些问题。
答案 2 :(得分:8)
抱歉,我不了解使用蓝牙设备打印的信息。 但是,我做了一些关于使用wifi进行打印的研究,并在GitHub中发布了该代码,如果需要,可以参考。Android-wifi-print - GitHub
这是原型的流程。
下面的课程将负责该原型中的所有打印作业。
<强> 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) {
}
}
在以下链接的帮助下,我创建了这个。
如果您要打印文件,请拨打打印(文件)
如果要下载文件并打印出来, 调用 downloadAndPrint(fileUrl,fileName)
答案 3 :(得分:7)
我能够整合的唯一印刷品是Bixolon SPP-R200。他们有一个不错的SDK,很容易找到。我正在寻找8 1/2 x 11的蓝牙功能,但现在这样的sdk似乎是一个相当高的订单
答案 4 :(得分:3)
Star Micronics有一个通过蓝牙(以及wifi /以太网和USB)进行Android打印的SDK。您可以在此处下载:http://www.starmicronics.com/support/SDKDocumentation.aspx。
如上所述,您无法在此时进行本地打印,因此您的选项可以是特定的打印机API或第三方打印应用程序。
根据我的经验,最好使用API而不是外部应用程序。最大的原因是您可以完全控制打印机行为。如果API是智能构建的,那么很容易实现。使用第三方应用程序是有限制的,因为您无法按照自己的方式自定义打印输出。
我链接到你的Star SDK有一个非常好的示例应用程序,可让您测试和自定义许多打印机功能,以便查看它们的运行情况。每个函数都记录在源代码中。这些命令及其参数也可以在应用程序本身中作为快速屏幕参考使用,这很方便。最重要的是,它有很好的记录。
如果选择这种方式,您可以将纯文本连同命令一起发送到打印机。 API处理将数据转换为打印机可以理解的内容。
答案 5 :(得分:2)
还有另一款适用于Android的打印SDK,名为APF。它基于CUPS,因此支持数千台打印机。网站:isb-vietnam.com
答案 6 :(得分:2)
Zebra Technologies还提供SDK for Android。我已经尝试了他们的SDK和Bixolon(通过写信到techsupp@bixolon.de得到它)。两者都运行正常,但如果您更喜欢使用page description language来定义文档,那么最好使用Zebra打印机。