connectAsync will sometimes always fail if the phone was restarted.

I've only seen this happen on Google Pixel devices but if I restart the phone there is a chance that I will be able to connect to the MMR board after 2-3 retries, and connecting via nRFConnect works fine too. But other times when I restart the phone I'm completely unable to connect via my app, via nRFConnect, or even Metabase unless I restart the phone a few more times. This happens on 2 seperate Google Pixel devices.

In my app I get this:
java.util.concurrent.TimeoutException: Failed to connect and discover services within 10000ms
when it fails along with these bluetooth gatt logs:
D/BluetoothGatt: connect() - device: <MAC address>, auto: false D/BluetoothGatt: registerApp() D/BluetoothGatt: registerApp() - UUID=<UUID number> D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6 D/BluetoothGatt: refresh() - device: <MAC address> D/BluetoothGatt: close() unregisterApp() - mClientIf=6
This repeats because I call onServiceConnected every time the task faults

In the case where everything is working I get these logs:
D/BluetoothGatt: connect() - device: <MAC address>, auto: false registerApp() registerApp() - UUID=<UUID number> D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7 D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=<MAC address> D/BluetoothGatt: onConnectionUpdated() - Device=<MAC address>interval=6 latency=0 timeout=500 status=0 D/BluetoothGatt: onConnectionUpdated() - Device=<MAC address> interval=36 latency=0 timeout=500 status=0 D/BluetoothGatt: discoverServices() - device: <MAC address> D/BluetoothGatt: onSearchComplete() = Device=<MAC address> Status=0 D/BluetoothGatt: setCharacteristicNotification() - uuid: <UUID number> enable: true

I need to make sure that I have some way of making the MMR work with most phones or at least know why it fails.
Why would it work sometimes but not others? And If it does work it seems to continue to work until the phone is turned off, at which point it's a coin flip if it works again or not. The behavior is basically the same with nRFConnect but seemingly only applies to the MMR board.

Comments

  • Are you able to play with the connection settings and experiment? We do advertise quite slowly so this could be an issue.

  • I'm trying now with a few different ones like raising advertising power. With default settings I'm always able to discover the device itself with a ble scan. The problem is actually connecting to it. Do you have any settings recommendations?

    Most advertising setting I've tried actually made it harder to discover the MMR.

  • edited January 2020

    Can you describe more of what happens when you try to connect?

  • If I attempt to connect via nRFConnect I will discover the device but on pressing "connect" it will load and will no reach services discovered. Metabase will show "unable to connect to device"

    And for my code I call

    connectAsync().onSuccessTask(...
    code for accel and gyro...
    ...
    then in the continueWith block I get the error:
    ' @Override
    public Void then(Task task) throws Exception {
    if (task.isFaulted()) {

                        task.getError().printStackTrace();
                        if(task.getError().getMessage().contains("discover")){
    
                        }'
    

    'java.util.concurrent.TimeoutException: Failed to connect and discover services within 10000ms'

    I'm not sure what it could be if I can't connect through metabase or nRFConnect half the time

    Here's logcat from trying with metabase if it's of any help:

    '2020-01-23 14:19:30.822 8481-8499/? D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=5 mScannerId=0
    2020-01-23 14:19:33.202 2567-2567/? W/adbd: timeout expired while flushing socket, closing
    2020-01-23 14:19:36.134 658-863/? I/nanohub: osLog: [AR_CHRE] still: 100
    2020-01-23 14:19:36.137 658-863/? I/nanohub: osLog: [AR_CHRE] ON => IDLE
    2020-01-23 14:19:36.477 8481-8481/? D/BluetoothAdapter: isLeEnabled(): ON
    2020-01-23 14:19:36.526 8481-8481/? D/BluetoothGatt: connect() - device: , auto: false
    2020-01-23 14:19:36.526 8481-8481/? D/BluetoothGatt: registerApp()
    2020-01-23 14:19:36.526 8481-8481/? D/BluetoothGatt: registerApp() - UUID=
    2020-01-23 14:19:36.528 1360-2212/? I/bt_stack: [INFO:gatt_api.cc(946)] GATT_Register
    2020-01-23 14:19:36.528 1360-2212/? I/bt_stack: [INFO:gatt_api.cc(966)] allocated gatt_if=5
    2020-01-23 14:19:36.528 8481-8499/? D/BluetoothGatt: onClientRegistered() - status=0 clientIf=5
    2020-01-23 14:19:36.530 1360-1491/? D/bt_btif_config: btif_get_address_type: Device [] address type 1
    2020-01-23 14:19:36.530 1360-1491/? D/bt_btif_config: btif_get_device_type: Device [] type 2
    2020-01-23 14:19:36.530 1360-2212/? I/bt_stack: [INFO:gatt_api.cc(1104)] GATT_Connectgatt_if=5, address=
    2020-01-23 14:19:46.529 8481-8538/? D/BluetoothGatt: refresh() - device:
    2020-01-23 14:19:46.533 8481-8538/? D/BluetoothGatt: close()
    2020-01-23 14:19:46.533 8481-8538/? D/BluetoothGatt: unregisterApp() - mClientIf=5
    2020-01-23 14:19:46.536 1360-2212/? I/bt_stack: [INFO:gatt_api.cc(1218)] GATT_Disconnect conn_id=000000
    2020-01-23 14:19:46.537 1360-2212/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=3 connected=0 conn_id=0x0003 reason=0x0016
    2020-01-23 14:19:46.537 1360-1491/? E/BtGatt.ContextMap: Context not found for ID 5
    2020-01-23 14:19:46.537 1360-2212/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=4 connected=0 conn_id=0x0004 reason=0x0016
    2020-01-23 14:19:46.537 1360-2212/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=5 connected=0 conn_id=0x0005 reason=0x0016
    2020-01-23 14:19:46.537 1360-2212/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=6 connected=0 conn_id=0x0006 reason=0x0016
    2020-01-23 14:19:46.567 891-2885/? E/InputDispatcher: Window handle Window{9567190 u0 com.mbientlab.metawear.metabase/com.mbientlab.metawear.metabase.HomeActivity} has no registered input channel
    2020-01-23 14:19:46.583 891-6489/? E/InputDispatcher: Window handle Window{9567190 u0 com.mbientlab.metawear.metabase/com.mbientlab.metawear.metabase.HomeActivity} has no registered input channel'

    The status code is "host terminated connection"

  • Please don't use the nRFConnect App. It could be corrupting the device. Only use the MetaBase App from now on until the troubleshooting is complete (don't use our APIs or your own code either).

    Please do all the steps here: www.mbientlab.com/troubleshooting.

    Get back to me on the failure error and include screenshots (preferably the diagnostic info too) as you go through the troubleshooting steps.

  • So actually after a couple failures to connect I finally managed to reset the app through metabase once. Since them I've restarted the phone about 10 times and tried to connect only with metabase, and only with this specific phone.
    So far like this it's connecting perfectly.
    I have 2 ideas for the problem i was getting:

    1.)
    When I was testing my app previously I had been using the same MMR with multiple phones in order to test the app. Is that likely to have been the issue? I'm leaning towards this because once the device connected once my app worked pretty consistently.

    2.)
    Otherwise I initiate a few different instances where I connect to the device through the app(for example one that just reads some accel data during the user setup and one to be used constantly in the background), but seemingly that never caused any issues(if it got sensor data during my app setup and I created a new instance after it would still work fine every time). Maybe less likely but having having multiple service instances calling connectAsync could be a problem( in that case I should make sure to unbind the service and tear down the board before moving to another instance?)

    I'm going to try testing my app with only this phone for some attempts to see if it's working consistently.

  • Trimmed down version of my app

    `public class MetaWearSensorManager implements ServiceConnection {

    private static MetaWearSensorManager SINGLE_INSTANCE = null;
    private String MW_MAC_ADDRESS;
    private BtleService.LocalBinder serviceBinder;
    private MetaWearBoard board;
    private Accelerometer accelerometer;
    private GyroBmi160 gyroBmi160;
    private Led led;
    private Settings settings;
    private BluetoothDevice remoteDevice;
    
    public MetaWearSensorManager(String macAddress) {
        MW_MAC_ADDRESS = macAddress;
        context.bindService(new Intent(context, BtleService.class),
                this, Context.BIND_AUTO_CREATE);
    }
    
    /**
     * @param macAddress MAC address of the mbientLab ble device
     * @return SINGLE_INSTANCE: the singleton istance of this class responsible for mblientlab interaction
     */
    public static MetaWearSensorManager getInstance(String macAddress) {
        if (SINGLE_INSTANCE == null) {
            synchronized(MetaWearSensorManager.class) {
                SINGLE_INSTANCE = new MetaWearSensorManager(macAddress);
            }
        }
        return SINGLE_INSTANCE;
    }
    
    
    public void retrieveBoard() throws Exception{
        // Get the MetaWear device via MAC address
        final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        remoteDevice = bluetoothManager.getAdapter().getRemoteDevice(MW_MAC_ADDRESS);
    
        // Create a MetaWear board object for the Bluetooth Device
        board = serviceBinder.getMetaWearBoard(remoteDevice);
    
    
    }
    
    
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder service){
        serviceBinder = (BtleService.LocalBinder) service;
        try {
            retrieveBoard();
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        try {
            board.connectAsync().onSuccessTask(new Continuation<Void, Task<Route>>() {
                @Override
                public Task<Route> then(Task<Void> task) throws Exception {
    
                    accelerometer = board.getModule(Accelerometer.class);
                    accelerometer.configure()
                            .odr(25f)       // Set sampling frequency to 25Hz, or closest valid ODR
                            .commit();
    
                    led = board.getModule(Led.class);
                    led.stop(true);
                    led.editPattern(Led.Color.GREEN, Led.PatternPreset.PULSE).commit();
                    led.play();
    
    
                    // Sets a macro to turn on a pulsing red red if the device gets disconnected
                    settings = board.getModule(Settings.class);
    
                    settings.onDisconnectAsync(new CodeBlock() {
                        @Override
                        public void program() {
                            led.stop(true);
                            led.editPattern(Led.Color.RED, Led.PatternPreset.PULSE).commit();
                            led.play();
                            board.tearDown();
                        }
                    });
    
    
                    // Adds a Stream route to access the accelerometer module features
                    return accelerometer.acceleration().addRouteAsync(new RouteBuilder() {
                        @Override
                        public void configure(RouteComponent source) {
                            source.stream(new Subscriber() {
                                @Override
                                public void apply(Data data, Object... env) {
                                    // Do things...
                                }
                            });
                        }
                    });
                }
            }).continueWith(new Continuation<Route, Void>() {
                @Override
                public Void then(Task<Route> task) throws Exception {
                    if (task.isFaulted()) {
    
                        Log.e(TAG, task.getError().toString());
                        task.getError().printStackTrace();
                        if(task.getError().getMessage().contains("discover")){
                        }
                        // Task Failed
    
                        // Disconnect and retry
                        board.disconnectAsync();
                        serviceBinder.removeMetaWearBoard(remoteDevice);
    
                        onServiceConnected(componentName, service);
    
                    } else {
                        // Task Worked
                        accelerometer.acceleration().start();
                        accelerometer.start();
                    }
                    return null;
                }
            }).continueWith(new Continuation<Void, Task<Void>>() {
                @Override
                public Task<Void> then(Task<Void> task) throws Exception {
                    gyroBmi160 = board.getModule(GyroBmi160.class);
                    gyroBmi160.configure()
                            .odr(GyroBmi160.OutputDataRate.ODR_25_HZ)
                            .range(GyroBmi160.Range.FSR_500)
                            .commit();
    
                    // Adds a Stream route to access the gyro module features
                    return gyroBmi160.angularVelocity().addRouteAsync(new RouteBuilder() {
                        @Override
                        public void configure(RouteComponent source) {
                            source.stream(new Subscriber() {
                                @Override
                                public void apply(Data data, Object... env) {
                    // Do things
    
    
    
                                }
                            });
    
                        }
                    }).continueWith(new Continuation<Route, Void>() {
                        @Override
                        public Void then(Task<Route> task) throws Exception {
                            if(task.isFaulted()){
                                Log.e(TAG, task.getError().toString());
                                // Task Failed
                                board.disconnectAsync();
                                onServiceConnected(componentName, service);
                            } else {
                                // Task Worked
                                gyroBmi160.angularVelocity().start();
                                gyroBmi160.start();
                            }
                            return null;
                        }
                    });
                }
            });
    
        } catch (Exception e){
            Log.i("MetaBoardReadings", e.getMessage().toString());
        }finally {
    
        }
    
        try {
            board.onUnexpectedDisconnect(new MetaWearBoard.UnexpectedDisconnectHandler() {
                @Override
                public void disconnected(int status) {
                    onServiceConnected(componentName, service);
                }
            });
        } catch (Exception e){e.printStackTrace();}
    }
    
    
    
    @Override
    public void onServiceDisconnected(ComponentName componentName) {
    
    }
    
    
    /**
     *  Called to blink a blue led when smoking is detected
     */
    public void blinkSmokingLed(){
        led.stop(true);
        led.editPattern(Led.Color.BLUE)
                .pulseDuration((short) 1000)
                .highIntensity((byte) 30)
                .commit();
        led.play();
    }
    

    `

  • edited January 2020

    Even when only using this instance I posted above it still fails frequently, but works if I ONLY use the metabase app. If I run my code and it happens to fail metabase will also frequently fail.

    There's nothing much to screenshot, metabase simply tries to connect and shows " Error
    Failed to connect to the device" in a dialog.

    Here are my logs while trying to connect with metabase AFTER failing to connect with my app after a restart:

    2561-2561/? W/adbd: timeout expired while flushing socket, closing 2561-2561/? W/adbd: timeout expired while flushing socket, closing 8919-8919/? D/BluetoothAdapter: isLeEnabled(): ON 8919-8919/? D/BluetoothGatt: connect() - device: <MAC>, auto: false 8919-8919/? D/BluetoothGatt: registerApp() 8919-8919/? D/BluetoothGatt: registerApp() - UUID= <UUID> 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(946)] GATT_Register <UUID> 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(966)] allocated gatt_if=6 8919-8936/? D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6 1367-1504/? D/bt_btif_config: btif_get_address_type: Device [<MAC>] address type 1 1367-1504/? D/bt_btif_config: btif_get_device_type: Device [<MAC>] type 2 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(1104)] GATT_Connectgatt_if=6, address=<MAC> 8919-9171/? D/BluetoothGatt: refresh() - device: <MAC> 8919-9171/? D/BluetoothGatt: close() 8919-9171/? D/BluetoothGatt: unregisterApp() - mClientIf=6 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(1218)] GATT_Disconnect conn_id=000000 1367-2118/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=3 connected=0 conn_id=0x0003 reason=0x0016 1367-1504/? E/BtGatt.ContextMap: Context not found for ID 6 1367-2118/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=4 connected=0 conn_id=0x0004 reason=0x0016 1367-2118/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=5 connected=0 conn_id=0x0005 reason=0x0016 1367-2118/? W/bt_stack: [WARNING:bta_gattc_act.cc(1044)] bta_gattc_conn_cback: cif=6 connected=0 conn_id=0x0006 reason=0x0016 912-5492/? E/InputDispatcher: Window handle Window{9c5827c u0 com.mbientlab.metawear.metabase/com.mbientlab.metawear.metabase.HomeActivity} has no registered input channel 912-5492/? E/InputDispatcher: Window handle Window{9c5827c u0 com.mbientlab.metawear.metabase/com.mbientlab.metawear.metabase.HomeActivity} has no registered input channel 8919-8919/? D/BluetoothAdapter: isLeEnabled(): ON 8919-8919/? D/BluetoothLeScanner: could not find callback wrapper 8919-8964/? D/OpenGLRenderer: endAllActiveAnimators on 0x770ebaeb00 (RippleDrawable) with handle 0x76a5a1e020 8919-8919/? D/BluetoothAdapter: isLeEnabled(): ON 912-5492/? E/InputDispatcher: Window handle Window{ac82ac u0 com.mbientlab.metawear.metabase/com.mbientlab.metawear.metabase.HomeActivity} has no registered input channel 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(946)] GATT_Register <UUID> 1367-2118/? I/bt_stack: [INFO:gatt_api.cc(966)] allocated gatt_if=6 8919-8936/? D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=6 mScannerId=0

  • @danielj
    Right now I am concerned that you didn't fully disconnect the sensor before trying to connect again (so of course it would fail since BLE is a 1:1 connection).

    This seemed especially likely based on your post where you mention using connectAsync multiple times as well as multiple devices.

    To get rid of this potential issue, you can turn off the BLE antenna and turn it back on on your device (smartphone/computer) before you try to connect. Also, make sure any and all other BLE devices are very far out of reach or fully turned off. You can get back to me on this once your tests are complete.

    Otherwise I can't comment too much on your code; I can only comment on MetaBase app usage. I am very much leaning towards the fact that you have not fully disconnected before attempting to connect (either via your app, metabase, or another device and so everyone is fighting for the connection to your sensor).

  • edited January 2020

    I tried only using a single device after a clear reset of the MMR. I've been pretty much using the code above. One possible issue is that I don't get to do any clean up on the connection because I'm reading sensor data constantly in the background(singleton instance with 15min alarm), if I or someone else decides to just shut off the phone there's nothing I can do about it.

    I suspect metabase does something else when it connects as well;

    Say my app is working, and I go ahead and restart my phone:
    1). On restart I launch my app, there is a good chance that I will not be able to discover services and use the MMR, if I try to use metabase now it will likely fail continuously.
    2.) On restart I launch metabase, after 1-3 attempts to connect metabase will successfully connect, if metabase does connect my app will work seemingly 100% after.

    If the phone is restarted it should be in the same state so why does it matter if I connect first with metabase or with my app?

    Additionally at the very end I waited for my app to fail on this phone and tried right after with a different phone and it works flawlessly?

    Is the code for how metabase connects available? Or is there some workaround like automatically resetting the board from a macro since I need the app to be able to work on multiple different devices.

  • Additionally at the very end I waited for my app to fail on this phone and tried right after with a different phone and it works flawlessly?

    You should handle auto reconnects in your app, bluetooth is not a flawless protocol and is very likely to fail to connect. Your app should always attempt to handle connect and connection failures.

    Is the code for how metabase connects available?

    The MetaBase is available for a fee, https://mbientlab.com/store/metabase-license/ (ios and android only)
    The MetaHub is available for free, just request the image (javascript only)

  • edited January 2020

    I handle disconnects by attempting to call onServiceConnected() again, and it works to reconnect the device if it comes out of range or anything like that.

    try { board.onUnexpectedDisconnect(new MetaWearBoard.UnexpectedDisconnectHandler() { @Override public void disconnected(int status) { onServiceConnected(componentName, service); } }); } catch (Exception e){e.printStackTrace();}

    Like I said the issue is only after the phone has been restarted, I can walk away or disconnect multiple times while the phone hasn't been restarted and it reconnects fine.

    The only weird situation is the first connection after the phone is restarted, if that one works(which it does consistently with metabase) then it continues to work while the phone is not shut off, it might take 2-3 tries from either my app or metabase but if it manages to connect even once it continues to for days after so long as the phone is not shut off.

    I'm trying to make sense of why the success rate for the first connection is so much higher on metabase.

  • Is it with one phone in particular or all phones? Can you tell us more about the OS and make/hardware of the phone?

  • Make: Google
    Model: PIxel (2016)
    Anroid OS: version 10
    Build version: QP1a. 191005.007.A3
    Board: sailfish
    Ble supported

    The other phones I've tried have worked fine, running android 8 and android 9. (galaxy s7 and note 9)

  • Do you have a phone that is not a Pixel and that is new-ish you can use?

  • @Laura said:
    Do you have a phone that is not a Pixel and that is new-ish you can use?

    Yes, like I said I have two phones that work. The problem is that we are trying to provide mmr's to other people and there's no way to know if their phones will have issues.

  • edited February 2020

    I think we have seen many issues with the Google Pixels phones. Unfortunately there is not much we can do about this. It has been reported by many users (not just metawear users) that the BLE stack (firmware/software) + antenna (hardware) on the Pixel phones is notoriously unreliable.

  • @danielj said:
    I'm trying to make sense of why the success rate for the first connection is so much higher on metabase.

    MetaBase does a BLE scan for the device selection UI. You can try using the BLE scan API to obtain the BluetoothDevice object instead of from the BluetoothAdapter class.

  • @Eric said:

    @danielj said:
    I'm trying to make sense of why the success rate for the first connection is so much higher on metabase.

    MetaBase does a BLE scan for the device selection UI. You can try using the BLE scan API to obtain the BluetoothDevice object instead of from the BluetoothAdapter class.

    So I have access to the Metabase code and tried scanning for MMR every time like you said before connecting but I still get the same issue:
    'E/MetaWearSensorManager: java.util.concurrent.TimeoutException: Failed to connect and discover services within 10000ms'

    The problem seems similar to this one: https://mbientlab.com/community/discussion/1772/status-129-error-discovering-bluetooth-services

    So I'm wondering if it's a threading issue?
    The way the app works is that an alarm will be triggered every 15 minutes and the class that connects to the accel/gyro is a singleton called from there(with the code from above)

    For some reason MetaBase is able to avoid getting this issue on restart while my app is not all the time.

    So basically if I run my app once it will work fine.
    Then I restart my phone, if I try to launch my app once again likely it will fail to discover services, but if I run MetaBase it will "fix" the problem. I'm trying to look through the source code to figure out why it does.

  • edited February 2020
                'Log.d("TAG", "prior to connectAsync");
                return metawear.connectAsync();
            }).continueWith(task -> {
                if (task.isFaulted()) {
                    Log.d("TAG", task.getError().getLocalizedMessage());
                    owner.runOnUiThread(() -> {
                        connDialog.dismiss();
                        new AlertDialog.Builder(owner)
                                .setTitle(R.string.title_error)
                                .setMessage(R.string.message_connect_fail)
                                .setPositiveButton(android.R.string.ok, (dialog, which) -> activityBus.navigateBack())
                                .create()
                                .show();
                    });'
    

    Is called from metabase to connect to the board, fails at line "return metawear.connectAsync();
    And the error is here in JseMetaboard:

                      if (task.isFaulted()) {
                            if (inMetaBootMode()) {
                                connected = true;
                                return Task.forResult(null);
                            } else {
                                if (task.getError() instanceof TaskTimeoutException) {
                                    Queue<ModuleInfo> partial = (Queue<ModuleInfo>) ((TaskTimeoutException) task.getError()).partial;
                                    for(ModuleInfo it: partial) {
                                        persist.boardInfo.moduleInfo.put(Constant.Module.lookupEnum(it.id), it);
                                        instantiateModule(it);
                                    }
                                }
    
                                return gatt.localDisconnectAsync().continueWithTask(ignored ->
                                        task.getError() instanceof TaskTimeoutException ? Task.forError((Exception) task.getError().getCause()) : task
                                );
    

    The error is a task timeout

    From my app I also scan for the ble device and fail at connectAsync() here:

               try {
                    board.onUnexpectedDisconnect(new MetaWearBoard.UnexpectedDisconnectHandler() {
                        @Override
                        public void disconnected(int status) {
                            board.disconnectAsync();
                            board.tearDown();
                            onServiceConnected(componentName, service);
                        }
                    });
                } catch (Exception e){e.printStackTrace();}
    
                try {
                    // ---------------------------------------------------------------------------------------------
                    board.connectAsync().onSuccessTask(new Continuation<Void, Task<Route>>() {
                        @Override
                        public Task<Route> then(Task<Void> task) throws Exception {
    

    Yet for some reason Metabase is successful on connecting as long as my app is not launched first.

  • I've been testing with a simpler app and get the same issue on the Pixel phone. The only thing that's driving me nuts is how if I try only with Metabase it works. Metabase will usually fail to connect 1 or 2 times but eventually will work.

    But both my apps seems to reach the connectAsync() timeout continuously and nothing I do seems to fix it besides lucking out on a phone restart or launching MetaBase first?? Are there any interesting things metabase does(We bought the source code for this) to manage to connect?

  • I think you are learning first-hand the difficulty in supporting all the Android Phones and Bluetooth (there is a LOT of variability between phones/hardware and OSs).

    All you can do is to try to gracefully handle misconnections and disconnects. That's what we do in MetaBase. We also cache devices so we can reconnect faster.

  • Another difficulty might be that I'm connecting to the device completely in the background so I can't use any of the ui-based mbientlab utilities.

    In my code I have the mac saved in prefs:
    App is started via alarm, scans for the device->
    That ble device is passed to a new singleton that implements serviceconnection(code I posted above)

    But the only real issue I get is "unable to discover services within 10000ms" so the connectAsync() times out,

    I've been looking at the Metabase Diagnostic fragment and I can't see much logically that differs from my app? After taking another look the starter app also works fine and I don't notice it doing anything fancy with misconnections/disconnects. Is there anyone in particular you recommend I look?

Sign In or Register to comment.