getBluetoothService() called with no BluetoothManagerCallback for Android Nexus 5

15,140

since android 4.2 , bluetooth stack changed, so i guess you are testing on android>=4.2 .

your problem is here tmp = device.createRfcommSocketToServiceRecord(MY_UUID); . this socket creation method is not compatible starting with 4.2 , so you will need to use the fallback one after it fails : tmp =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);

Don't worry about called with no BluetoothManagerCallback being thrown, it doesn't matter.

So if you do it like this, it will work:

        try {
            socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);
        } catch (Exception e) {Log.e("","Error creating socket");}

        try {
            socket.connect();
            Log.e("","Connected");
        } catch (IOException e) {
            Log.e("",e.getMessage());
            try {
                Log.e("","trying fallback...");

                socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);
                socket.connect();

                Log.e("","Connected");
            }

also, i answered here more detailed, about a similar problem.

Share:
15,140
Larry Lo
Author by

Larry Lo

Code with passion.

Updated on June 05, 2022

Comments

  • Larry Lo
    Larry Lo about 2 years

    I am going to implemenet the module for sending commands from my Android smartphone to HC-06 via BLuetooth. WHen it comes to the execution , it show s the following exception and find no clue for the error message as title . Would you please tell the way to modifiy ?

    Exception Log Message :

     07-29 13:51:37.701: W/BluetoothAdapter(1928): getBluetoothService() called with no BluetoothManagerCallback
        07-29 13:51:37.711: D/BluetoothSocket(1928): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[51]}
        07-29 13:51:42.831: W/System.err(1928): java.io.IOException: read failed, socket might closed or timeout, read ret: -1
        07-29 13:51:42.831: W/System.err(1928):     at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:505)
        07-29 13:51:42.831: W/System.err(1928):     at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:516)
        07-29 13:51:42.831: W/System.err(1928):     at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:320)
        07-29 13:51:42.831: W/System.err(1928):     at com.luugiathuy.apps.remotebluetooth.BluetoothCommandService$ConnectThread.run(BluetoothCommandService.java:260)
        07-29 13:51:42.831: D/BluetoothCommandService(1928): setState() 2 -> 1
    

    The below is my code

    public class BluetoothCommandService {
        // Debugging
        private static final String TAG = "BluetoothCommandService";
        private static final boolean D = true;
    
        // Unique UUID for this application
       // private static final UUID MY_UUID = UUID.fromString("04c6093b-0000-1000-8000-00805f9b34fb");
    
        private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
    
        // Member fields
        private final BluetoothAdapter mAdapter;
        private final Handler mHandler;
        private ConnectThread mConnectThread;
        private ConnectedThread mConnectedThread;
        private int mState;
    //    private BluetoothDevice mSavedDevice;
    //    private int mConnectionLostCount;
    
        // 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
    
        // Constants that indicate command to computer
        public static final int EXIT_CMD = -1;
        public static final int VOL_UP = 1;
        public static final int VOL_DOWN = 2;
        public static final int MOUSE_MOVE = 3;
    
        /**
         * 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 BluetoothCommandService(Context context, Handler handler) {
            mAdapter = BluetoothAdapter.getDefaultAdapter();
            mState = STATE_NONE;
            //mConnectionLostCount = 0;
            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(RemoteBluetooth.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 ConnectThread to initiate a connection to a remote device.
         * @param device  The BluetoothDevice to connect
         */
        public synchronized void connect(BluetoothDevice device) {
            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;}
    
            // Start the thread to connect with the given device
            mConnectThread = new ConnectThread(device);
            mConnectThread.start();
            setState(STATE_CONNECTING);
        }
    
        /**
         * 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) {
            if (D) Log.d(TAG, "connected");
    
            // 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;}
    
            // Start the thread to manage the connection and perform transmissions
            mConnectedThread = new ConnectedThread(socket);
            mConnectedThread.start();
    
            // Send the name of the connected device back to the UI Activity
            Message msg = mHandler.obtainMessage(RemoteBluetooth.MESSAGE_DEVICE_NAME);
            Bundle bundle = new Bundle();
            bundle.putString(RemoteBluetooth.DEVICE_NAME, device.getName());
            msg.setData(bundle);
            mHandler.sendMessage(msg);
    
            // save connected device
            //mSavedDevice = device;
            // reset connection lost count
            //mConnectionLostCount = 0;
    
            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;}
    
            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);
        }
    
        public void write(int 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() {
            setState(STATE_LISTEN);
    
            // Send a failure message back to the Activity
            Message msg = mHandler.obtainMessage(RemoteBluetooth.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(RemoteBluetooth.TOAST, "Unable to connect device");
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    
        /**
         * Indicate that the connection was lost and notify the UI Activity.
         */
        private void connectionLost() {
    //        mConnectionLostCount++;
    //        if (mConnectionLostCount < 3) {
    //          // Send a reconnect message back to the Activity
    //          Message msg = mHandler.obtainMessage(RemoteBluetooth.MESSAGE_TOAST);
    //          Bundle bundle = new Bundle();
    //          bundle.putString(RemoteBluetooth.TOAST, "Device connection was lost. Reconnecting...");
    //          msg.setData(bundle);
    //          mHandler.sendMessage(msg);
    //          
    //          connect(mSavedDevice);      
    //        } else {
                setState(STATE_LISTEN);
                // Send a failure message back to the Activity
                Message msg = mHandler.obtainMessage(RemoteBluetooth.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString(RemoteBluetooth.TOAST, "Device connection was lost");
                msg.setData(bundle);
                mHandler.sendMessage(msg);
    //        }
        }
    
        /**
         * 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;
    
            public ConnectThread(BluetoothDevice device) {
                mmDevice = device;
                BluetoothSocket tmp = null;
    
                // Get a BluetoothSocket for a connection with the
                // given BluetoothDevice
                try {
                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
                } catch (IOException e) {
                    Log.e(TAG, "create() failed", e);
                }
                mmSocket = tmp;
            }
    
            public void run() {
                Log.i(TAG, "BEGIN mConnectThread");
                setName("ConnectThread");
    
                // 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) {
                    e.printStackTrace();
                    connectionFailed();
                    // Close the socket
                    try {
                        mmSocket.close();
                    } catch (IOException e2) {
                        Log.e(TAG, "unable to close() socket during connection failure", e2);
                    }
                    // Start the service over to restart listening mode
                    BluetoothCommandService.this.start();
                    return;
                }
    
                // Reset the ConnectThread because we're done
                synchronized (BluetoothCommandService.this) {
                    mConnectThread = null;
                }
    
                // Start the connected thread
                connected(mmSocket, mmDevice);
            }
    
            public void cancel() {
                try {
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "close() of connect 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) {
                Log.d(TAG, "create ConnectedThread");
                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;
            }
    
            public void run() {
                Log.i(TAG, "BEGIN mConnectedThread");
                byte[] buffer = new byte[1024];
    
                // Keep listening to the InputStream while connected
                while (true) {
                    try {
                        // Read from the InputStream
                        int bytes = mmInStream.read(buffer);
    
                        // Send the obtained bytes to the UI Activity
                        mHandler.obtainMessage(RemoteBluetooth.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);
                    mmOutStream.flush();
                    // Share the sent message back to the UI Activity
    //                mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
    //                        .sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "Exception during write", e);
                }
            }
    
            public void write(int out) {
                try {
                    mmOutStream.write(out);
    
                    // Share the sent message back to the UI Activity
    //                mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
    //                        .sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "Exception during write", e);
                }
            }
    
            public void cancel() {
                try {
                    mmOutStream.write(EXIT_CMD);
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "close() of connect socket failed", e);
                }
            }
        }
    }
    

    Here is my Activity

    public class RemoteBluetooth extends Activity {
    
        // Layout view
        private TextView mTitle;
    
        // Intent request codes
        private static final int REQUEST_CONNECT_DEVICE = 1;
        private static final int REQUEST_ENABLE_BT = 2;
    
        // Message types sent from the BluetoothChatService Handler
        public static final int MESSAGE_STATE_CHANGE = 1;
        public static final int MESSAGE_READ = 2;
        public static final int MESSAGE_WRITE = 3;
        public static final int MESSAGE_DEVICE_NAME = 4;
        public static final int MESSAGE_TOAST = 5;
    
        // Key names received from the BluetoothCommandService Handler
        public static final String DEVICE_NAME = "device_name";
        public static final String TOAST = "toast";
    
        // Name of the connected device
        private String mConnectedDeviceName = null;
        // Local Bluetooth adapter
        private BluetoothAdapter mBluetoothAdapter = null;
        // Member object for Bluetooth Command Service
        private BluetoothCommandService mCommandService = null;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Set up the window layout
            requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
            setContentView(R.layout.main);
            getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
    
            // Set up the custom title
            mTitle = (TextView) findViewById(R.id.title_left_text);
            mTitle.setText(R.string.app_name);
            mTitle = (TextView) findViewById(R.id.title_right_text);
    
            // Get local Bluetooth adapter
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    
            // If the adapter is null, then Bluetooth is not supported
            if (mBluetoothAdapter == null) {
                Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
                finish();
                return;
            }
        }
    
        @Override
        protected void onStart() {
            super.onStart();
    
            // If BT is not on, request that it be enabled.
            // setupCommand() will then be called during onActivityResult
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
            }
            // otherwise set up the command service
            else {
                if (mCommandService==null)
                    setupCommand();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            // Performing this check in onResume() covers the case in which BT was
            // not enabled during onStart(), so we were paused to enable it...
            // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
            if (mCommandService != null) {
                if (mCommandService.getState() == BluetoothCommandService.STATE_NONE) {
                    mCommandService.start();
                }
            }
        }
    
        private void setupCommand() {
            // Initialize the BluetoothChatService to perform bluetooth connections
            mCommandService = new BluetoothCommandService(this, mHandler);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            if (mCommandService != null)
                mCommandService.stop();
        }
    
        private void ensureDiscoverable() {
            if (mBluetoothAdapter.getScanMode() !=
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                startActivity(discoverableIntent);
            }
        }
    
        // The Handler that gets information back from the BluetoothChatService
        private final Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case MESSAGE_STATE_CHANGE:
                    switch (msg.arg1) {
                    case BluetoothCommandService.STATE_CONNECTED:
                        mTitle.setText(R.string.title_connected_to);
                        mTitle.append("HC-06");
                        break;
                    case BluetoothCommandService.STATE_CONNECTING:
                        mTitle.setText(R.string.title_connecting);
                        break;
                    case BluetoothCommandService.STATE_LISTEN:
                    case BluetoothCommandService.STATE_NONE:
                        mTitle.setText(R.string.title_not_connected);
                        break;
                    }
                    break;
                case MESSAGE_DEVICE_NAME:
                    // save the connected device's name
                    mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                    Toast.makeText(getApplicationContext(), "Connected to "
                                   + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                    break;
                case MESSAGE_TOAST:
                    Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                                   Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        };
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
            case REQUEST_CONNECT_DEVICE:
                // When DeviceListActivity returns with a device to connect
                if (resultCode == Activity.RESULT_OK) {
                    // Get the device MAC address
                    String address = data.getExtras()
                                         .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
                    // Get the BLuetoothDevice object
                    BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
                    // Attempt to connect to the device
                    mCommandService.connect(device);
                }
                break;
            case REQUEST_ENABLE_BT:
                // When the request to enable Bluetooth returns
                if (resultCode == Activity.RESULT_OK) {
                    // Bluetooth is now enabled, so set up a chat session
                    setupCommand();
                } else {
                    // User did not enable Bluetooth or an error occured
                    Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                    finish();
                }
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.option_menu, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.scan:
                // Launch the DeviceListActivity to see devices and do scan
                Intent serverIntent = new Intent(this, DeviceListActivity.class);
                startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                return true;
            case R.id.discoverable:
                // Ensure this device is discoverable by others
                ensureDiscoverable();
                return true;
            }
            return false;
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
    
                String blinkCommand = "&$V00X77V0" ;
                String empty = "";
                for (int i = 0 ; i < (100 - blinkCommand.length()) ; i ++){
                    empty += "0";
                }
                String limiter = "\r\n";
    
                String fullCommand = blinkCommand +  empty + limiter;
                mCommandService.write(fullCommand.getBytes());
        //      mCommandService.write(BluetoothCommandService.VOL_UP);
                return true;
            }
            else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
                String blinkCommand = "&$V00X77V0" + "\r\n";
                mCommandService.write(blinkCommand.getBytes());
            //  mCommandService.write(BluetoothCommandService.VOL_DOWN);
                return true;
            }
    
            return super.onKeyDown(keyCode, event);
        }
    }