Search code examples
javaandroidbluetooth-lowenergyuart

Cannot initialize UART service on Android


I am developing mobile app which working with sensor, that use UART. Example from official github page works perfect, but code extracted from doesnt work. Only thing that i have changed, is a device search, but this code works perfect with Polar H7 device(only discovering device name and device adress and sending to next activity). On this activity i am trying to connect to UART device, here is code :

public class UartRecordingActivity extends AppCompatActivity {

    private final static String TAG = UartRecordingActivity.class.getSimpleName();

    // BLE stuff
    public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
    public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";


    //private BleService bleService;

    private String deviceName;
    private String deviceAddress;

    //private BleServicesAdapter gattServiceAdapter;

    private boolean isConnected = false;



    private static final int REQUEST_SELECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;
    private static final int UART_PROFILE_READY = 10;
    private static final int UART_PROFILE_CONNECTED = 20;
    private static final int UART_PROFILE_DISCONNECTED = 21;
    private static final int STATE_OFF = 10;
    private int mState = UART_PROFILE_DISCONNECTED;

    private UartService mService = null;
    private BluetoothDevice mDevice = null;
    private BluetoothAdapter mBtAdapter = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recording_uart);

        Log.i(TAG, "onCreate");

        final Intent intent = getIntent();
        deviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
        deviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);

        final Intent gattServiceIntent = new Intent(this, UartService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);

    }

    @Override
    protected void onStart() {
        super.onStart();

        mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        service_init();

        mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(deviceAddress);
        mService.connect(deviceAddress);
    }

    private void service_init() {
        Intent bindIntent = new Intent(this, UartService.class);
        bindService(bindIntent, mServiceConnection, BIND_AUTO_CREATE);

        LocalBroadcastManager.getInstance(this).registerReceiver(UARTStatusChangeReceiver,
                makeGattUpdateIntentFilter());
    }

    //UART service connected/disconnected
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder rawBinder) {
            mService = ((UartService.LocalBinder) rawBinder).getService();
            Log.d(TAG, "onServiceConnected mService= " + mService);
            if (!mService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }

        }


        public void onServiceDisconnected(ComponentName classname) {
            mService = null;
        }
    };


    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem) {
        if (menuItem.getItemId() == android.R.id.home) {
            Intent intent = new Intent(this, HomeActivity.class);
            startActivity(intent);
        }
        return super.onOptionsItemSelected(menuItem);}

private final BroadcastReceiver UARTStatusChangeReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        final Intent mIntent = intent;
        //*********************//
        if (action.equals(UartService.ACTION_GATT_CONNECTED)) {
            runOnUiThread(new Runnable() {
                public void run() {
                    String currentDateTimeString = DateFormat.getTimeInstance().format(new Date());
                    Log.d(TAG, "UART_CONNECT_MSG");

                    mState = UART_PROFILE_CONNECTED;
                }
            });
        }

        //*********************//
        if (action.equals(UartService.ACTION_GATT_DISCONNECTED)) {

            runOnUiThread(new Runnable() {
                public void run() {
                    String currentDateTimeString = DateFormat.getTimeInstance().format(new Date());
                    Log.d(TAG, "UART_DISCONNECT_MSG");
                    mState = UART_PROFILE_DISCONNECTED;
                    mService.close();
                }
            });
        }

        //*********************//
        if (action.equals(UartService.ACTION_GATT_SERVICES_DISCOVERED)) {
            mService.enableTXNotification();
        }
        //*********************//
        if (action.equals(UartService.ACTION_DATA_AVAILABLE)) {
            Log.i("data","received");
            final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
            //handle data
        }
        //*********************//
        if (action.equals(UartService.DEVICE_DOES_NOT_SUPPORT_UART)) {
        }

    }
};




    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(UartService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(UartService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(UartService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(UartService.ACTION_DATA_AVAILABLE);
        intentFilter.addAction(UartService.DEVICE_DOES_NOT_SUPPORT_UART);
        return intentFilter;
    }
}

Error is caused by this line(mService causing NullPointerException):

mService.connect(deviceAddress);

Solution

  • Method OnServiceConnected is guarantees that you have been connected to service by binding. In OnStart callback you have NullPointer because when you call bindService, it needs a little time to make a connection. Just make your code something like that:

    public void onServiceConnected(ComponentName className, IBinder rawBinder) {
        mService = ((UartService.LocalBinder) rawBinder).getService();
        Log.d(TAG, "onServiceConnected mService= " + mService);
        if (!mService.initialize()) {
            Log.e(TAG, "Unable to initialize Bluetooth");
            finish();
        }
        mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(deviceAddress);
        mService.connect(deviceAddress);
    }