与Android使用手持式蓝牙打印机
我有一个蓝牙手持打印机,可以使用我的Mac(使用Coolterm)使用SPP连接进行通信。 当我试图从Android(使用平台7)做同样的事情时,我遇到了很多问题:
-
打印机似乎不支持/需要PIN身份validation。 当从OSX进行连接时,我只是select了“不使用引脚”的选项并将其配对。 在Android中,当我使用
device.createRfcommSocketToServiceRecord()
,它总是要求我input一个PIN / Key(我没有/需要)。 我使用reflection技巧解决了这个问题:Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class}); BluetoothSocket connection = (BluetoothSocket) m.invoke(device, 1);
我不确定这是否真正起作用,但是打印机上的闪烁LED不再闪烁,这使我相信这样做。
-
一旦我有套接字,我尝试写字节数据的stream使用:
byte[] buffer = new byte[3]; buffer[0] = (byte) 0x8A; buffer[1] = (byte) 0xC1; buffer[2] = (byte) 0x04; outStream.write(buffer); int response = inStream.read(); mySocket.close();
在OSX上从Coolterm发送相同的三字节序列从打印机打印testing页。 但是,这似乎使线程挂在Android(读)。
有什么我在这里错过吗?
编辑:这似乎只有当我把通道设置为1。所以这意味着我在这里的东西。
@Trevor页面我认为是在正确的道路上。 这里是我用来连接到一个基本的邮票微控制器的谷歌的例子。
/ * *版权(C)2009 Android开源项目 * *根据Apache许可证2.0版(“许可证”)获得许可; *除遵守许可证外,您不得使用此文件。 *您可以在获得许可证副本 * * http://www.apache.org/licenses/LICENSE-2.0 * *除非适用法律要求或书面同意,软件 *根据许可证分发是“按现状”分发的, *无任何明示或暗示的保证或条件。 *请参阅许可证以了解特定语言的pipe理权限和权限 *许可证下的限制。 * / package com.your_package; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; 导入android.bluetooth.BluetoothAdapter; 导入android.bluetooth.BluetoothDevice; 导入android.bluetooth.BluetoothServerSocket; 导入android.bluetooth.BluetoothSocket; 导入android.content.Context; 导入android.os.Bundle; 导入android.os.Handler; 导入android.os.Message; 导入android.util.Log; / ** *此课程负责设置和pipe理蓝牙的所有工作 *与其他设备的连接。 它有一个线程,倾听 *传入连接,用于连接设备的线程和一个 *连接时执行数据传输的线程。 * / 公共类BluetoothService { //debugging private static final String TAG =“BluetoothService_BoeBot”; private static final boolean D = true; //创build服务器套接字时,SDPlogging的名称 private static final String NAME_SECURE =“BluetoothSecure”; private static final String NAME_INSECURE =“BluetoothInsecure”; //此应用程序的唯一UUID 私有静态最终的UUID MY_UUID_SECURE = UUID.fromString( “00001101-0000-1000-8000-00805F9B34FB”); 私有静态最终UUID MY_UUID_INSECURE = UUID.fromString( “00001101-0000-1000-8000-00805F9B34FB”); //会员字段 私人最终BluetoothAdapter mAdapter; 私人最终处理程序mHandler; private AcceptThread mSecureAcceptThread; private AcceptThread mInsecureAcceptThread; 私有ConnectThread mConnectThread; 私人ConnectedThread mConnectedThread; private int mState; //指示当前连接状态的常量 公共静态最终诠释STATE_NONE = 0; //我们什么都不做 公共静态最终诠释STATE_LISTEN = 1; //现在正在监听传入的连接 公共静态最终诠释STATE_CONNECTING = 2; //现在启动一个传出连接 公共静态最终诠释STATE_CONNECTED = 3; //现在连接到远程设备 / ** *构造函数。 准备一个新的蓝牙聊天会话。 * @param上下文UI活动上下文 * @param处理程序将消息发送回UI活动的处理程序 * / 公共BluetoothService(上下文上下文,处理程序处理程序) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } / ** *设置聊天连接的当前状态 * @param state定义当前连接状态的整数 * / 私有同步无效setState(int状态) { (D) Log.d(TAG,“setState()”+ mState +“ - >”+ state); mState =状态; //将新状态赋予处理程序,以便UI活动可以更新 mHandler.obtainMessage(BoeBot.MESSAGE_STATE_CHANGE,state,-1).sendToTarget(); } / ** *返回当前的连接状态。 * / 公共同步诠释getState() { 返回mState; } / ** *开始聊天服务。 具体启动AcceptThread来开始一个 *监听(服务器)模式的会话。 由Activity onResume()调用* / public synchronized void start() { (D) Log.d(TAG,“开始”); //取消任何尝试build立连接的线程 如果(mConnectThread!= null) { mConnectThread.cancel(); mConnectThread = null; } //取消当前正在运行连接的任何线程 如果(mConnectedThread!= null) { mConnectedThread.cancel(); mConnectedThread = null; } 的setState(STATE_LISTEN); //启动线程以侦听BluetoothServerSocket 如果(mSecureAcceptThread == null) { mSecureAcceptThread = new AcceptThread(true); mSecureAcceptThread.start(); } 如果(mInsecureAcceptThread == null) { mInsecureAcceptThread = new AcceptThread(false); mInsecureAcceptThread.start(); } } / ** *启动ConnectThread以启动到远程设备的连接。 * @param设备BluetoothDevice连接 * @param安全套接字安全types - 安全(true),不安全(false) * / 公共同步无效连接(BluetoothDevice设备,布尔安全) { (D) Log.d(TAG,“connect to:”+ device); //取消任何尝试build立连接的线程 如果(mState == STATE_CONNECTING) { 如果(mConnectThread!= null) { mConnectThread.cancel(); mConnectThread = null; } } //取消当前正在运行连接的任何线程 如果(mConnectedThread!= null) { mConnectedThread.cancel(); mConnectedThread = null; } 尝试 { //开始线程连接给定的设备 mConnectThread = new ConnectThread(设备,安全); mConnectThread.start(); 的setState(STATE_CONNECTING); catch(Exception e) { } } / ** *启动ConnectedThread开始pipe理蓝牙连接 * @param socket已连接的BluetoothSocket * @参数设备已连接的BluetoothDevice * / public synchronized void connected(BluetoothSocket socket,BluetoothDevice device,final String socketType) { (D) Log.d(TAG,“connected,Socket Type:”+ socketType); //取消完成连接的线程 如果(mConnectThread!= null) { mConnectThread.cancel(); mConnectThread = null; } //取消当前正在运行连接的任何线程 如果(mConnectedThread!= null) { mConnectedThread.cancel(); mConnectedThread = null; } //取消接受线程,因为我们只想连接到一个设备 如果(mSecureAcceptThread!= null) { mSecureAcceptThread.cancel(); mSecureAcceptThread = null; } 如果(mInsecureAcceptThread!= null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } //启动线程来pipe理连接并执行传输 mConnectedThread = new ConnectedThread(socket,socketType); mConnectedThread.start(); //将连接设备的名称发送回UI活动 消息msg = mHandler.obtainMessage(BoeBot.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(BoeBot.DEVICE_NAME,device.getName()); msg.setData(束); mHandler.sendMessage(MSG); 的setState(STATE_CONNECTED); } / ** *停止所有线程 * / 公共同步无效停止() { (D) Log.d(TAG,“stop”); 如果(mConnectThread!= null) { mConnectThread.cancel(); mConnectThread = null; } 如果(mConnectedThread!= null) { mConnectedThread.cancel(); mConnectedThread = null; } 如果(mSecureAcceptThread!= null) { mSecureAcceptThread.cancel(); mSecureAcceptThread = null; } 如果(mInsecureAcceptThread!= null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } 的setState(STATE_NONE); } / ** *以不同步的方式写入ConnectedThread * @param out要写入的字节 *参见ConnectedThread#write(byte []) * / public void write(byte [] out) { //创build临时对象 ConnectedThread r; //同步ConnectedThread的副本 同步(这个) { 如果(mState!= STATE_CONNECTED) 返回; r = mConnectedThread; } //执行写入不同步 r.write(下); } / ** *表示连接尝试失败并通知UI活动。 * / private void connectionFailed() { //发送失败消息回到活动 消息msg = mHandler.obtainMessage(BoeBot.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BoeBot.TOAST,“无法连接设备”); msg.setData(束); mHandler.sendMessage(MSG); //启动服务以重新启动监听模式 BluetoothService.this.start(); } / ** *表示连接丢失并通知UI活动。 * / 私人无效connectionLost() { //发送失败消息回到活动 消息msg = mHandler.obtainMessage(BoeBot.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BoeBot.TOAST,“设备连接丢失”); msg.setData(束); mHandler.sendMessage(MSG); //启动服务以重新启动监听模式 BluetoothService.this.start(); } / ** *此线程在侦听传入连接时运行。 它的行为 *像服务器端的客户端。 它运行,直到连接被接受 *(或直到取消)。 * / 私有类AcceptThread扩展了Thread { //本地服务器套接字 私人最终BluetoothServerSocket mmServerSocket; 私人stringmSocketType; 公共AcceptThread(布尔安全) { BluetoothServerSocket tmp = null; mSocketType =安全吗? “安全”:“不安全”; //创build一个新的侦听服务器套接字 尝试 { 如果(安全) { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,MY_UUID_SECURE); }别的 { tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord( NAME_INSECURE,MY_UUID_INSECURE); } catch(IOException e) { Log.e(TAG,“Socket Type:”+ mSocketType +“listen()failed”,e); } mmServerSocket = tmp; } @覆盖 public void run() { (D) { Log.d(TAG,“Socket Type:”+ mSocketType +“BEGIN mAcceptThread”+ this); } setName(“AcceptThread”+ mSocketType); BluetoothSocket socket = null; //如果我们没有连接,请收听服务器套接字 while(mState!= STATE_CONNECTED) { 尝试 { //这是一个阻塞调用,只会返回一个 //成功连接或exception socket = mmServerSocket.accept(); catch(IOException e) { Log.e(TAG,“Socket Type:”+ mSocketType +“accept()failed”,e); 打破; } //如果连接被接受 if(socket!= null) { 同步(BluetoothService.this) { 开关(mState) { 情况STATE_LISTEN: 情况STATE_CONNECTING: //情况正常。 开始连接的线程。 连接(socket,socket.getRemoteDevice(),mSocketType); 打破; 情况STATE_NONE: 情况STATE_CONNECTED: //未准备好或已经连接。 终止新的套接字。 尝试 { socket.close(); catch(IOException e) { Log.e(TAG,“无法closures不需要的套接字”,e); } 打破; } } } } (D) { Log.i(TAG,“END mAcceptThread,socket Type:”+ mSocketType); } } public void cancel() { (D) { Log.d(TAG,“Socket Type”+ mSocketType +“cancel”+ this); } 尝试 { mmServerSocket.close(); catch(IOException e) { Log.e(TAG,“套接字types”+ mSocketType +“服务器的close()失败”,e); } } } / ** *此线程在尝试build立传出连接时运行 *用设备。 它贯穿始终; 连接要么 *成功或失败。 * / 私有类ConnectThread扩展了Thread { 私人最终BluetoothSocket mmSocket; 私人最终的BluetoothDevice设备; 私人stringmSocketType; 公共ConnectThread(BluetoothDevice设备,布尔安全) { mmDevice = device; BluetoothSocket tmp = null; mSocketType =安全吗? “安全”:“不安全”; //获取与蓝牙连接的BluetoothSocket //给出BluetoothDevice 尝试 { 如果(安全) { tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE); }别的 { tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE); } catch(IOException e) { Log.e(TAG,“Socket Type:”+ mSocketType +“create()failed”,e); } mmSocket = tmp; } @覆盖 public void run() { Log.i(TAG,“BEGIN mConnectThread SocketType:”+ mSocketType); setName(“ConnectThread”+ mSocketType); //总是取消发现,因为它会减慢连接速度 mAdapter.cancelDiscovery(); //连接到BluetoothSocket 尝试 { //这是一个阻塞调用,只会返回一个 //成功连接或exception mmSocket.connect(); catch(IOException e) { //closures套接字 尝试 { mmSocket.close(); catch(IOException e2) { Log.e(TAG,“无法在连接失败时closures()”+ mSocketType +“套接字”,e2); } 连接失败(); 返回; } //重置ConnectThread,因为我们完成了 同步(BluetoothService.this) { mConnectThread = null; } 尝试 { //启动连接的线程 连接(mmSocket,mmDevice,mSocketType); catch(Exception e) { Log.e(TAG,“”,e); } } public void cancel() { 尝试 { mmSocket.close(); catch(IOException e) { Log.e(TAG,“连接的close()”+ mSocketType +“套接字失败”,e); } } } / ** *此线程在与远程设备连接期间运行。 *它处理所有传入和传出的传输。 * / 私有类ConnectedThread扩展了Thread { 私人最终BluetoothSocket mmSocket; 私人最终InputStream mmInStream; 私人最终OutputStream mmOutStream; 公共ConnectedThread(BluetoothSocket套接字,string套接字types) { Log.d(TAG,“创buildConnectedThread:”+ socketType); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; //获取BluetoothSocketinput和输出stream 尝试 { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); catch(IOException e) { Log.e(TAG,“未创build临时套接字”,e); } mmInStream = tmpIn; mmOutStream = tmpOut; } @覆盖 public void run() { Log.i(TAG,“BEGIN mConnectedThread”); byte [] buffer = new byte [1024]; int字节; //连接时保持监听InputStream 而(真) { 尝试 { //从InputStream中读取 bytes = mmInStream.read(buffer); //将获得的字节发送到UI活动 mHandler.obtainMessage(BoeBot.MESSAGE_READ,bytes,-1,buffer).sendToTarget(); catch(IOException e) { Log.e(TAG,“disconnected”,e); connectionLost(); 打破; } } } / ** *写入连接的OutStream。 * @param buffer要写入的字节 * / public void write(byte [] buffer) { 尝试 { mmOutStream.write(缓冲液); //将发送的消息分享回UI活动 mHandler.obtainMessage(BoeBot.MESSAGE_WRITE,-1,-1,buffer).sendToTarget(); catch(IOException e) { Log.e(TAG,“写入期间的exception”,e); } } public void cancel() { 尝试 { mmSocket.close(); catch(IOException e) { Log.e(TAG,“连接套接字的close()失败”,e); } } } }
testing看它是否工作。
BluetoothService mService = new BluetoothService(this, mHandler); mService.write(Bytes);
Google云打印