How to keep Bluetooth connection background?

13,842

Yes, I found a working solution for running Bluetooth background in Android. Below is the code I have used in my android app.

public class BluetoothServices extends Service {

    private BluetoothAdapter mBluetoothAdapter;
    public static final String B_DEVICE = "MY DEVICE";
    public static final String B_UUID = "00001101-0000-1000-8000-00805f9b34fb";
    // 00000000-0000-1000-8000-00805f9b34fb

    public static final int STATE_NONE = 0;
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    private ConnectBtThread mConnectThread;
    private static ConnectedBtThread mConnectedThread;

    private static Handler mHandler = null;
    public static int mState = STATE_NONE;
    public static String deviceName;
    public static BluetoothDevice sDevice = null;
    public Vector<Byte> packData = new Vector<>(2048);

    //IBinder mIBinder = new LocalBinder();


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //mHandler = getApplication().getHandler();
        return mBinder;
    }
    public void toast(String mess){
        Toast.makeText(this,mess,Toast.LENGTH_SHORT).show();
    }
    private final IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        BluetoothServices getService() {
            // Return this instance of LocalService so clients can call public methods
            return BluetoothServices.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        String deviceg = intent.getStringExtra("bluetooth_device");


        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

                connectToDevice(deviceg);

        return START_STICKY;
    }
    private synchronized void connectToDevice(String macAddress){
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
        if (mState == STATE_CONNECTING){
            if (mConnectThread != null){
                mConnectThread.cancel();
                mConnectThread = null;
            }
        }
        if (mConnectedThread != null){
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        mConnectThread = new ConnectBtThread(device);
        toast("connecting");
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }
    private void setState(int state){
        mState = state;
        if (mHandler != null){
           // mHandler.obtainMessage();
        }
    }
    public synchronized void stop(){
        setState(STATE_NONE);
        if (mConnectThread != null){
            mConnectThread.cancel();
            mConnectThread = null;
        }
        if (mConnectedThread != null){
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mBluetoothAdapter != null){
            mBluetoothAdapter.cancelDiscovery();
        }

        stopSelf();
    }

    public void sendData(String message){
        if (mConnectedThread!= null){
            mConnectedThread.write(message.getBytes());
            toast("sent data");
        }else {
            Toast.makeText(BluetoothServices.this,"Failed to send data",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean stopService(Intent name) {
        setState(STATE_NONE);

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

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

        mBluetoothAdapter.cancelDiscovery();
        return super.stopService(name);
    }

    /*private synchronized void connected(BluetoothSocket mmSocket){

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

        mConnectedThread = new ConnectedBtThread(mmSocket);
        mConnectedThread.start();


        setState(STATE_CONNECTED);
    }*/

    private class ConnectBtThread extends Thread{
        private final BluetoothSocket mSocket;
        private final BluetoothDevice mDevice;

        public ConnectBtThread(BluetoothDevice device){
            mDevice = device;
            BluetoothSocket socket = null;
            try {
                socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
            } catch (IOException e) {
                e.printStackTrace();
            }
            mSocket = socket;

        }

        @Override
        public void run() {
            mBluetoothAdapter.cancelDiscovery();

            try {
                mSocket.connect();
                Log.d("service","connect thread run method (connected)");
                SharedPreferences pre = getSharedPreferences("BT_NAME",0);
                pre.edit().putString("bluetooth_connected",mDevice.getName()).apply();

            } catch (IOException e) {

                try {
                    mSocket.close();
                    Log.d("service","connect thread run method ( close function)");
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
            //connected(mSocket);
            mConnectedThread = new ConnectedBtThread(mSocket);
            mConnectedThread.start();
        }

        public void cancel(){

            try {
                mSocket.close();
                Log.d("service","connect thread cancel method");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private class ConnectedBtThread extends Thread{
        private final BluetoothSocket cSocket;
        private final InputStream inS;
        private final OutputStream outS;

        private byte[] buffer;

        public ConnectedBtThread(BluetoothSocket socket){
            cSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = socket.getInputStream();

            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            inS = tmpIn;
            outS = tmpOut;
        }

        @Override
        public void run() {
            buffer = new byte[1024];
            int mByte;
            try {
                mByte= inS.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            Log.d("service","connected thread run method");

        }


        public void write(byte[] buff){
            try {
                outS.write(buff);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void cancel(){
            try {
                cSocket.close();
                Log.d("service","connected thread cancel method");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onDestroy() {
        this.stop();
        super.onDestroy();
    }
}
Share:
13,842

Related videos on Youtube

Bhanu Prakash Pasupula
Author by

Bhanu Prakash Pasupula

Failure by choise, an entrepreneur by passion.

Updated on June 04, 2022

Comments

  • Bhanu Prakash Pasupula
    Bhanu Prakash Pasupula about 2 years

    I have created a Bluetooth Activity class in the android app, which works fine for all the Bluetooth functionalities like: scanning, pairing, connecting, sending and receiving data.

    The real problem is when the Activity is destroyed. Bluetooth is disconnecting.

    how can I make Bluetooth connection throughout the app. and I want to send data to the Bluetooth from other activities.

    Help me to implement this in an easy way?

    public class BTActivity extends AppCompatActivity {
    
    ArrayList<BluetoothDevice> devices = new ArrayList<>();
    BluetoothAdapter mBluetoothAdapter;
    BluetoothDevice mBluetoothDevice;
    ArrayAdapter<BluetoothDevice> arrayAdapter;
    
    ConnectThread c;
    
    private static final String TAG = "MY_BT";
    
    ListView lvPaired;
    Button BluetoothOnOff, ScanBt, pairedlist, sendButton, btDisconnect, incrementBtn, decrementBtn;
    EditText input_text;
    TextView ConnectedTo;
    
    FragmentManager fm = getSupportFragmentManager();
    
    UUID BHANU_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bt);
    
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        lvPaired = findViewById(R.id.btPairedLV);
        pairedlist = findViewById(R.id.btPaired);
        input_text = findViewById(R.id.user_input);
        sendButton = findViewById(R.id.btnSend);
        BluetoothOnOff = findViewById(R.id.offOn_bt);
        ScanBt = findViewById(R.id.scan_bt);
        ConnectedTo = findViewById(R.id.current_connected_bluetooth);
        btDisconnect = findViewById(R.id.bt_disconnect);
        incrementBtn = findViewById(R.id.incrementBtn);
        decrementBtn = findViewById(R.id.decrementBtn);
    
        onClickListener();
        pairedList();
    
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(mReceiver, filter);
    
    }
    public void onClickListener(){
    
        pairedlist.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (arrayAdapter != null){
                    arrayAdapter.clear();
                }
                pairedList();
            }
        });
    
        lvPaired.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                BluetoothDevice device = (BluetoothDevice) parent.getItemAtPosition(position);
                c = new ConnectThread(device, true);
                c.start();
            }
        });
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String text = input_text.getText().toString();
                c.sendData(text);
                input_text.setText("");
    
            }
        });
        BluetoothOnOff.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!mBluetoothAdapter.isEnabled()){
                    mBluetoothAdapter.enable();
                    BluetoothOnOff.setText("ON");
                }else {
                    mBluetoothAdapter.disable();
                    BluetoothOnOff.setText("OFF");
                }
            }
        });
        ScanBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ScanFragment scanFragment = new ScanFragment();
                scanFragment.show(fm,"ScanBT");
                //ScanFragment scanFragment = new ScanFragment();
                //scanFragment.show(fm,"Scan Fragment");
            }
        });
        btDisconnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                c.cancel();
            }
        });
    
        incrementBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                c.sendData("a");
            }
        });
        decrementBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                c.sendData("b");
            }
        });
    
    }
    
    
    public void toast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
    
    @Override
    protected void onDestroy() {
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }
    
    public void pairedList() {
        //arrayAdapter.clear();
        devices.addAll(mBluetoothAdapter.getBondedDevices());
        arrayAdapter = new ArrayAdapter<BluetoothDevice>(this, android.R.layout.simple_list_item_1,android.R.id.text1, devices);
        lvPaired.setAdapter(arrayAdapter);
        arrayAdapter.notifyDataSetChanged();
    
    }
    
    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                toast("connected");
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                ConnectedTo.setText(device.getName());
                btDisconnect.setVisibility(View.VISIBLE);
                //getActionBar().setSubtitle(device.getName());
                Log.d("BT", "connected to");
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                toast("disconnected");
                ConnectedTo.setText("None");
                btDisconnect.setVisibility(View.INVISIBLE);
               // getActionBar().setSubtitle("");
                Log.d("BT", "disconnected");
            }
    
        }
    };
    
    
    public class ConnectThread extends Thread {
        BluetoothDevice cDevice;
        BluetoothSocket socket;
        ConnectedThread ct;
    
        ConnectThread(BluetoothDevice device, boolean insecureConnection) {
            cDevice = device;
            try {
                if (insecureConnection) {
                    socket = device.createInsecureRfcommSocketToServiceRecord(BHANU_UUID);
                } else {
                    socket = device.createRfcommSocketToServiceRecord(BHANU_UUID);
                }
            } catch (IOException e) {
                e.getMessage();
            }
        }
    
        public void run() {
            mBluetoothAdapter.cancelDiscovery();
    
            try {
                Log.d("BT", "Socket ready to connect");
                socket.connect();
                Log.d("BT", "Socket connected");
                // out = socket.getOutputStream();
                // input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    
    
            } catch (final IOException e) {
                e.getMessage();
            }
    
            ct = new ConnectedThread(socket);
    
            //ct.write("Q-smart".getBytes());
                /*try {
                    socket.close();
                } catch (final IOException closeException) {
                    closeException.getMessage();
                }*/
        }
        private void sendData(String message){
            Log.d(TAG,message);
            if (socket != null){
                ct.write(message.getBytes());
            }else {
                toast("Please connect to bluetooth first");
            }
        }
    
        public void cancel() {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private byte[] mmBuffer; // mmBuffer store for the stream
    
        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
    
            // Get the input and output streams; using temp objects because
            // member streams are final.
            try {
                tmpIn = socket.getInputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating input stream", e);
            }
            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating output stream", e);
            }
    
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }
    
        public void run() {
            mmBuffer = new byte[1024];
            int numBytes; // bytes returned from read()
    
            // Keep listening to the InputStream until an exception occurs.
            while (true) {
                try {
                    // Read from the InputStream.
                    numBytes = mmInStream.read(mmBuffer);
                    // Send the obtained bytes to the UI activity.
                   /* Message readMsg = mHandler.obtainMessage(
                            MessageConstants.MESSAGE_READ, numBytes, -1,
                            mmBuffer);
                    readMsg.sendToTarget();*/
                } catch (IOException e) {
                    Log.d(TAG, "Input stream was disconnected", e);
                    break;
                }
            }
        }
    
        // Call this from the main activity to send data to the remote device.
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
    
                // Share the sent message with the UI activity.
               /* Message writtenMsg = mHandler.obtainMessage(
                        MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
                writtenMsg.sendToTarget();*/
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when sending data", e);
    
                // Send a failure message back to the activity.
               /* Message writeErrorMsg =
                        mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString("toast",
                        "Couldn't send data to the other device");
                writeErrorMsg.setData(bundle);
                mHandler.sendMessage(writeErrorMsg);*/
            }
        }
    
    
    }
    }