与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云打印