2011-11-09 10 views
36

Mam ręczną drukarkę bluetooth, która jest w stanie komunikować się za pomocą połączenia SPP z mojego komputera Mac (używając Coolterm). Kiedy staram się zrobić to samo z Android (przy użyciu platformy 7) Używam do wielu zagadnień:Używanie ręcznej drukarki bluetooth z Androidem

  • Drukarka nie wydają się potwierdzać/potrzebujemy uwierzytelniania PIN. Podczas łączenia się z OSX, właśnie wybrałem opcję "Nie używaj szpilki" i została sparowana. W Androidzie, kiedy używam device.createRfcommSocketToServiceRecord(), zawsze pojawia się pytanie o PIN/klucz (którego nie mam/potrzebuję). I rozwiązać to za pomocą sztuczki refleksji:

    Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class}); 
    BluetoothSocket connection = (BluetoothSocket) m.invoke(device, 1); 
    

    jestem pewien, czy to faktycznie działa, ale miga dioda drukarka przestanie migać, co sprawia mi uwierzyć, że to zrobił.

  • Raz mam gniazdo, staram się napisać bajt danych do strumienia przy użyciu:

    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(); 
    

    Wysyłanie samą sekwencję trzech bajtów z Coolterm na OSX wydrukowanie strony testowej z drukarki. Wydaje się jednak, że wątek zawiesił się na Androidzie (czytaj).

Czy jest tu coś, czego tu brakuje?

EDYCJA: Wydaje się, że działa tylko wtedy, gdy ustawiam kanał na 1. To oznacza, że ​​jestem na czymś tutaj.

+0

Czy używasz identyfikatora UDP SPP? ('prywatny statyczny ostateczny UUID MY_UUID = UUID.fromString (" 00001101-0000-1000-8000-00805F9B34FB ");') - Prawdopodobnie tak jest, i możliwe, że drukarka nie zaakceptuje połączenia, jeśli nie, ale myślałem, że i tak będę musiał się upewnić. – Trevor

+0

Metoda 'createInsecureRfcommSocket' nie akceptuje UUID jako parametru, tylko kanał. Tworzenie bezpiecznego kanału nie jest opcją, ponieważ nie mam kodu PIN. – navjotk

+0

Czy próbowałeś, aby działało z publicznym interfejsem API, który pobiera UUID? http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord%28java.util.UUID%29 wiem, że to tylko w późniejszej wersji android SDK, ale warto spróbować sprawdzić, czy to zadziała –

Odpowiedz

10

@Trevor Page myślę, że był na właściwej ścieżce. Oto przykład google'a, który użyłem do połączenia z podstawowym mikrokontrolerem.

 

    /* 
    * Copyright (C) 2009 The Android Open Source Project 
    * 
    * Licensed under the Apache License, Version 2.0 (the "License"); 
    * you may not use this file except in compliance with the License. 
    * You may obtain a copy of the License at 
    * 
    *  http://www.apache.org/licenses/LICENSE-2.0 
    * 
    * Unless required by applicable law or agreed to in writing, software 
    * distributed under the License is distributed on an "AS IS" BASIS, 
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    * See the License for the specific language governing permissions and 
    * limitations under the License. 
    */ 
    package com.your_package; 

    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import java.util.UUID; 

    import android.bluetooth.BluetoothAdapter; 
    import android.bluetooth.BluetoothDevice; 
    import android.bluetooth.BluetoothServerSocket; 
    import android.bluetooth.BluetoothSocket; 
    import android.content.Context; 
    import android.os.Bundle; 
    import android.os.Handler; 
    import android.os.Message; 
    import android.util.Log; 

    /** 
    * This class does all the work for setting up and managing Bluetooth 
    * connections with other devices. It has a thread that listens for 
    * incoming connections, a thread for connecting with a device, and a 
    * thread for performing data transmissions when connected. 
    */ 
    public class BluetoothService 
    { 
     // Debugging 
     private static final String TAG = "BluetoothService_BoeBot"; 
     private static final boolean D = true; 
     // Name for the SDP record when creating server socket 
     private static final String NAME_SECURE = "BluetoothSecure"; 
     private static final String NAME_INSECURE = "BluetoothInsecure"; 
     // Unique UUID for this application 
     private static final UUID MY_UUID_SECURE = 
       UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 
     private static final UUID MY_UUID_INSECURE = 
       UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 


     // Member fields 
     private final BluetoothAdapter mAdapter; 
     private final Handler mHandler; 
     private AcceptThread mSecureAcceptThread; 
     private AcceptThread mInsecureAcceptThread; 
     private ConnectThread mConnectThread; 
     private ConnectedThread mConnectedThread; 
     private int mState; 
     // Constants that indicate the current connection state 
     public static final int STATE_NONE = 0;  // we're doing nothing 
     public static final int STATE_LISTEN = 1;  // now listening for incoming connections 
     public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection 
     public static final int STATE_CONNECTED = 3; // now connected to a remote device 

     /** 
     * Constructor. Prepares a new BluetoothChat session. 
     * @param context The UI Activity Context 
     * @param handler A Handler to send messages back to the UI Activity 
     */ 
     public BluetoothService(Context context, Handler handler) 
     { 
      mAdapter = BluetoothAdapter.getDefaultAdapter(); 
      mState = STATE_NONE; 
      mHandler = handler; 
     } 


     /** 
     * Set the current state of the chat connection 
     * @param state An integer defining the current connection state 
     */ 
     private synchronized void setState(int state) 
     { 
      if (D) 
       Log.d(TAG, "setState() " + mState + " -> " + state); 

      mState = state; 

      // Give the new state to the Handler so the UI Activity can update 
      mHandler.obtainMessage(BoeBot.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); 
     } 

     /** 
     * Return the current connection state. */ 
     public synchronized int getState() 
     { 
      return mState; 
     } 

     /** 
     * Start the chat service. Specifically start AcceptThread to begin a 
     * session in listening (server) mode. Called by the Activity onResume() */ 
     public synchronized void start() 
     { 
      if (D) 
       Log.d(TAG, "start"); 

      // Cancel any thread attempting to make a connection 
      if (mConnectThread != null) 
      { 
       mConnectThread.cancel(); 
       mConnectThread = null; 
      } 

      // Cancel any thread currently running a connection 
      if (mConnectedThread != null) 
      { 
       mConnectedThread.cancel(); 
       mConnectedThread = null; 
      } 

      setState(STATE_LISTEN); 

      // Start the thread to listen on a BluetoothServerSocket 
      if (mSecureAcceptThread == null) 
      { 
       mSecureAcceptThread = new AcceptThread(true); 
       mSecureAcceptThread.start(); 
      } 
      if (mInsecureAcceptThread == null) 
      { 
       mInsecureAcceptThread = new AcceptThread(false); 
       mInsecureAcceptThread.start(); 
      } 
     } 

     /** 
     * Start the ConnectThread to initiate a connection to a remote device. 
     * @param device The BluetoothDevice to connect 
     * @param secure Socket Security type - Secure (true) , Insecure (false) 
     */ 
     public synchronized void connect(BluetoothDevice device, boolean secure) 
     { 
      if (D) 
       Log.d(TAG, "connect to: " + device); 

      // Cancel any thread attempting to make a connection 
      if (mState == STATE_CONNECTING) 
      { 

       if (mConnectThread != null) 
       { 
        mConnectThread.cancel(); 
        mConnectThread = null; 
       } 
      } 

      // Cancel any thread currently running a connection 
      if (mConnectedThread != null) 
      { 
       mConnectedThread.cancel(); 
       mConnectedThread = null; 
      } 

      try 
      { 
       // Start the thread to connect with the given device 
       mConnectThread = new ConnectThread(device, secure); 
       mConnectThread.start(); 
       setState(STATE_CONNECTING); 
      }catch(Exception e) 
      { 

      } 
     } 

     /** 
     * Start the ConnectedThread to begin managing a Bluetooth connection 
     * @param socket The BluetoothSocket on which the connection was made 
     * @param device The BluetoothDevice that has been connected 
     */ 
     public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) 
     { 
       if (D) 
        Log.d(TAG, "connected, Socket Type:" + socketType); 

       // Cancel the thread that completed the connection 
       if (mConnectThread != null) 
       { 
        mConnectThread.cancel(); 
        mConnectThread = null; 
       } 

       // Cancel any thread currently running a connection 
       if (mConnectedThread != null) 
       { 
        mConnectedThread.cancel(); 
        mConnectedThread = null; 
       } 

       // Cancel the accept thread because we only want to connect to one device 
       if (mSecureAcceptThread != null) 
       { 
        mSecureAcceptThread.cancel(); 
        mSecureAcceptThread = null; 
       } 
       if (mInsecureAcceptThread != null) 
       { 
        mInsecureAcceptThread.cancel(); 
        mInsecureAcceptThread = null; 
       } 

       // Start the thread to manage the connection and perform transmissions 
       mConnectedThread = new ConnectedThread(socket, socketType); 
       mConnectedThread.start(); 

       // Send the name of the connected device back to the UI Activity 
       Message msg = mHandler.obtainMessage(BoeBot.MESSAGE_DEVICE_NAME); 
       Bundle bundle = new Bundle(); 
       bundle.putString(BoeBot.DEVICE_NAME, device.getName()); 
       msg.setData(bundle); 
       mHandler.sendMessage(msg); 

       setState(STATE_CONNECTED); 

     } 

     /** 
     * Stop all threads 
     */ 
     public synchronized void stop() 
     { 
      if (D) 
       Log.d(TAG, "stop"); 

      if (mConnectThread != null) 
      { 
       mConnectThread.cancel(); 
       mConnectThread = null; 
      } 

      if (mConnectedThread != null) 
      { 
       mConnectedThread.cancel(); 
       mConnectedThread = null; 
      } 

      if (mSecureAcceptThread != null) 
      { 
       mSecureAcceptThread.cancel(); 
       mSecureAcceptThread = null; 
      } 

      if (mInsecureAcceptThread != null) 
      { 
       mInsecureAcceptThread.cancel(); 
       mInsecureAcceptThread = null; 
      } 
      setState(STATE_NONE); 
     } 

     /** 
     * Write to the ConnectedThread in an unsynchronized manner 
     * @param out The bytes to write 
     * @see ConnectedThread#write(byte[]) 
     */ 
     public void write(byte[] out) 
     { 
      // Create temporary object 
      ConnectedThread r; 
      // Synchronize a copy of the ConnectedThread 
      synchronized (this) 
      { 
       if (mState != STATE_CONNECTED) 
        return; 

       r = mConnectedThread; 
      } 
      // Perform the write unsynchronized 
      r.write(out); 
     } 

     /** 
     * Indicate that the connection attempt failed and notify the UI Activity. 
     */ 
     private void connectionFailed() 
     { 
      // Send a failure message back to the Activity 
      Message msg = mHandler.obtainMessage(BoeBot.MESSAGE_TOAST); 
      Bundle bundle = new Bundle(); 
      bundle.putString(BoeBot.TOAST, "Unable to connect device"); 
      msg.setData(bundle); 
      mHandler.sendMessage(msg); 

      // Start the service over to restart listening mode 
      BluetoothService.this.start(); 
     } 

     /** 
     * Indicate that the connection was lost and notify the UI Activity. 
     */ 
     private void connectionLost() 
     { 
      // Send a failure message back to the Activity 
      Message msg = mHandler.obtainMessage(BoeBot.MESSAGE_TOAST); 
      Bundle bundle = new Bundle(); 
      bundle.putString(BoeBot.TOAST, "Device connection was lost"); 
      msg.setData(bundle); 
      mHandler.sendMessage(msg); 

      // Start the service over to restart listening mode 
      BluetoothService.this.start(); 
     } 

     /** 
     * This thread runs while listening for incoming connections. It behaves 
     * like a server-side client. It runs until a connection is accepted 
     * (or until cancelled). 
     */ 
     private class AcceptThread extends Thread 
     { 
      // The local server socket 
      private final BluetoothServerSocket mmServerSocket; 
      private String mSocketType; 

      public AcceptThread(boolean secure) 
      { 

       BluetoothServerSocket tmp = null; 
       mSocketType = secure ? "Secure" : "Insecure"; 

       // Create a new listening server socket 
       try 
       { 
        if (secure) 
        { 
         tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE); 
        } else 
        { 
         tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
           NAME_INSECURE, MY_UUID_INSECURE); 
        } 
       } catch (IOException e) 
       { 
        Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e); 
       } 
       mmServerSocket = tmp; 
      } 

      @Override 
      public void run() 
      { 
       if (D) 
       { 
        Log.d(TAG, "Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this); 
       } 
       setName("AcceptThread" + mSocketType); 

       BluetoothSocket socket = null; 

       // Listen to the server socket if we're not connected 
       while (mState != STATE_CONNECTED) 
       { 
        try 
        { 
         // This is a blocking call and will only return on a 
         // successful connection or an exception 
         socket = mmServerSocket.accept(); 
        } catch (IOException e) 
        { 
         Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e); 
         break; 
        } 

        // If a connection was accepted 
        if (socket != null) 
        { 
         synchronized (BluetoothService.this) 
         { 
          switch (mState) 
          { 
           case STATE_LISTEN: 
           case STATE_CONNECTING: 
            // Situation normal. Start the connected thread. 
            connected(socket, socket.getRemoteDevice(), mSocketType); 
            break; 
           case STATE_NONE: 
           case STATE_CONNECTED: 
            // Either not ready or already connected. Terminate new socket. 
            try 
            { 
             socket.close(); 
            } catch (IOException e) 
            { 
             Log.e(TAG, "Could not close unwanted socket", e); 
            } 
            break; 
          } 
         } 
        } 
       } 
       if (D) 
       { 
        Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType); 
       } 

      } 

      public void cancel() 
      { 
       if (D) 
       { 
        Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this); 
       } 
       try 
       { 
        mmServerSocket.close(); 
       } catch (IOException e) 
       { 
        Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e); 
       } 
      } 
     } 

     /** 
     * This thread runs while attempting to make an outgoing connection 
     * with a device. It runs straight through; the connection either 
     * succeeds or fails. 
     */ 
     private class ConnectThread extends Thread 
     { 
      private final BluetoothSocket mmSocket; 
      private final BluetoothDevice mmDevice; 
      private String mSocketType; 

      public ConnectThread(BluetoothDevice device, boolean secure) 
      { 
       mmDevice = device; 
       BluetoothSocket tmp = null; 
       mSocketType = secure ? "Secure" : "Insecure"; 

       // Get a BluetoothSocket for a connection with the 
       // given BluetoothDevice 
       try 
       { 
        if (secure) 
        { 
         tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE); 
        } else 
        { 
         tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE); 
        } 
       } catch (IOException e) 
       { 
        Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e); 
       } 
       mmSocket = tmp; 
      } 

      @Override 
      public void run() 
      { 
       Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType); 
       setName("ConnectThread" + mSocketType); 

       // Always cancel discovery because it will slow down a connection 
       mAdapter.cancelDiscovery(); 

       // Make a connection to the BluetoothSocket 
       try 
       { 
        // This is a blocking call and will only return on a 
        // successful connection or an exception 
        mmSocket.connect(); 
       } catch (IOException e) 
       { 
        // Close the socket 
        try 
        { 
         mmSocket.close(); 
        } catch (IOException e2) 
        { 
         Log.e(TAG, "unable to close() " + mSocketType + " socket during connection failure", e2); 
        } 
        connectionFailed(); 
        return; 
       } 

       // Reset the ConnectThread because we're done 
       synchronized (BluetoothService.this) 
       { 
        mConnectThread = null; 
       } 

       try 
       { 
        // Start the connected thread 
        connected(mmSocket, mmDevice, mSocketType); 
       }catch(Exception e) 
       { 
        Log.e(TAG, "", e); 
       } 
      } 

      public void cancel() 
      { 
       try 
       { 
        mmSocket.close(); 
       } catch (IOException e) 
       { 
        Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e); 
       } 
      } 
     } 

     /** 
     * This thread runs during a connection with a remote device. 
     * It handles all incoming and outgoing transmissions. 
     */ 
     private class ConnectedThread extends Thread 
     { 
      private final BluetoothSocket mmSocket; 
      private final InputStream mmInStream; 
      private final OutputStream mmOutStream; 

      public ConnectedThread(BluetoothSocket socket, String socketType) 
      { 
       Log.d(TAG, "create ConnectedThread: " + socketType); 
       mmSocket = socket; 
       InputStream tmpIn = null; 
       OutputStream tmpOut = null; 

       // Get the BluetoothSocket input and output streams 
       try 
       { 
        tmpIn = socket.getInputStream(); 
        tmpOut = socket.getOutputStream(); 
       } catch (IOException e) 
       { 
        Log.e(TAG, "temp sockets not created", e); 
       } 

       mmInStream = tmpIn; 
       mmOutStream = tmpOut; 
      } 

      @Override 
      public void run() 
      { 
       Log.i(TAG, "BEGIN mConnectedThread"); 
       byte[] buffer = new byte[1024]; 
       int bytes; 

       // Keep listening to the InputStream while connected 
       while (true) 
       { 
        try 
        { 
         // Read from the InputStream 
         bytes = mmInStream.read(buffer); 

         // Send the obtained bytes to the UI Activity 
         mHandler.obtainMessage(BoeBot.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
        } catch (IOException e) 
        { 
         Log.e(TAG, "disconnected", e); 
         connectionLost(); 
         break; 
        } 
       } 
      } 

      /** 
      * Write to the connected OutStream. 
      * @param buffer The bytes to write 
      */ 
      public void write(byte[] buffer) 
      { 
       try 
       { 
        mmOutStream.write(buffer); 

        // Share the sent message back to the UI Activity 
        mHandler.obtainMessage(BoeBot.MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); 
       } catch (IOException e) 
       { 
        Log.e(TAG, "Exception during write", e); 
       } 
      } 

      public void cancel() 
      { 
       try 
       { 
        mmSocket.close(); 
       } catch (IOException e) 
       { 
        Log.e(TAG, "close() of connect socket failed", e); 
       } 
      } 
     } 
    } 

Sprawdź, czy działa.

BluetoothService mService = new BluetoothService(this, mHandler); 
mService.write(Bytes); 
-6
+1

Chce połączyć się przez Bluetooth, a nie z komputerem i drukarką w biurze lub w domu. – blindstuff

+0

Jest to konkretna drukarka termiczna na bluetooth, o której konkretnie mówię tutaj. Google Cloud Print jest dobry na ogólne rozwiązanie. – navjotk

+0

Najbrudniejsze obejście. – ruX

Powiązane problemy