1

I am currently attempting to make the app I am developing more simple to use but I am running into an issue trying to consolidate the amount of buttons needed to establish connection to a PSoC 4 BLE. In the end I want one button to handle searching, connecting, and discovery of services. But when I copy and past the code (for search, connecting, and discovering) under the method that handles activating the Bluetooth radio, the app crash when it encounters the scan callback. I am still new to Android app development and I am trying to use the debugger but I seem to be stuck. The first snippet of code is what I am trying to do, the second snippet is the scan function that is being called. The following snippet is the debugger output.

//what I am trying to do
    public void startBluetooth(View view) {

        /** Find BLE service and adapter */
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

        /** Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
        // fire an intent to display a dialog asking the user to grant permission to enable it. */
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BLE);
        }

        /** Start the BLE Service */
        Log.d(TAG, "Starting BLE Service");
        Intent gattServiceIntent = new Intent(this, PSoCCapSenseLEDService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);


        /** Disable the start button and turn on the search  button */
        start_button.setEnabled(false);
        search_button.setEnabled(true);
        Log.d(TAG, "Bluetooth is Enabled");



        // search function does not crash app
        // cannot force step into if statement, is mServiceConnected true?
        // no mServiceConnected appears to false
        // okay let's force this if statement to be executed
        // but first setting code back to normal and seeing how mServiceConnected is set

       mPSoCCapSenseLedService.scan(); // causes crash
        mPSoCCapSenseLedService.connect(); // crash
        mPSoCCapSenseLedService.discoverServices();
    }
    public void scan() {
        /** Scan for devices and look for the one with the service that we want
         *   UUID ending in F0 i.e. the ledcapsense service*/
        UUID capsenseLedService = UUID.fromString(capsenseLedServiceUUID);
        UUID[] capsenseLedServiceArray = {capsenseLedService};

        /** Use old scan method for versions for different platform versions */
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            /** noinspection deprecation */
            mBluetoothAdapter.startLeScan(capsenseLedServiceArray, mLeScanCallback);
        } else { /** New BLE scanning introduced in LOLLIPOP */
            ScanSettings settings;
            List<ScanFilter> filters;
            mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
            settings = new ScanSettings.Builder()
                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                    .build();
            filters = new ArrayList<>();
            /** We will scan just for the CAR's UUID */
            ParcelUuid PUuid = new ParcelUuid(capsenseLedService);
            ScanFilter filter = new ScanFilter.Builder().setServiceUuid(PUuid).build();
            filters.add(filter);
            mLEScanner.startScan(filters, settings, mScanCallback);
        }
    }
this.mResolvedMethod = No such instance field: 'mResolvedMethod'
this = {MainActivity@9661} 
view = {AppCompatButton@9664} "android.support.v7.widget.AppCompatButton{60e52c VF.D..C.. ...P..ID 64,64-1376,256 #7f07008a app:id/start_button}"
bluetoothManager = {BluetoothManager@9665} 
 mAdapter = {BluetoothAdapter@9666} 
 shadow$_klass_ = {Class@3343} "class android.bluetooth.BluetoothManager"
 shadow$_monitor_ = 0
mBluetoothAdapter = {BluetoothAdapter@9666} 
 mBleExtSupportArr = {boolean[1]@9772} 
 mBleSupportArr = {boolean[6]@9773} 
 mBluetoothDisableBleCallback = {BluetoothAdapter$4@9774} 
 mBluetoothStateChangeCallback = {BluetoothAdapter$3@9775} 
 mContext = {Application@9688} 
 mIsBleExtSupportArrSet = false
 mIsBleSupportArrSet = false
 mLeScanClients = {HashMap@9776}  size = 0
 mLock = {Object@9777} 
 mManagerCallback = {BluetoothAdapter$2@9778} 
 mManagerService = {IBluetoothManager$Stub$Proxy@9779} 
 mMyPid = 32668
 mMyUid = 10025
 mPackageName = "iantempleton0.gmail.com.fromscratch"
 mProxyServiceStateCallbacks = {ArrayList@9781}  size = 0
 mService = {IBluetooth$Stub$Proxy@9782} 
 mServiceLock = {ReentrantReadWriteLock@9783} "java.util.concurrent.locks.ReentrantReadWriteLock@366f373[Write locks = 0, Read locks = 0]"
 mStateChangedCallbacks = {ArrayList@9784}  size = 0
 mSwitchingUser = false
 mToken = {Binder@9785} 
 packageNameforEnable = ""
 shadow$_klass_ = {Class@5364} "class android.bluetooth.BluetoothAdapter"
 shadow$_monitor_ = 0
gattServiceIntent = {Intent@9667} "Intent { cmp=iantempleton0.gmail.com.fromscratch/.PSoCCapSenseLEDService }"
 mAction = null
 mCategories = null
 mClipData = null
 mComponent = {ComponentName@9789} "ComponentInfo{iantempleton0.gmail.com.fromscratch/iantempleton0.gmail.com.fromscratch.PSoCCapSenseLEDService}"
 mContentUserHint = -2
 mData = null
 mExtras = null
 mFlags = 0
 mForceLaunchOverTargetTask = false
 mIdentifier = null
 mLaunchOverTargetTaskId = 0
 mLaunchToken = null
 mPackage = null
 mPairActivityUserId = 0
 mPairWindowingMode = 0
 mSelector = null
 mSourceBounds = null
 mType = null
 shadow$_klass_ = {Class@3753} "class android.content.Intent"
 shadow$_monitor_ = 0
search_button = {AppCompatButton@9668} "android.support.v7.widget.AppCompatButton{b1d2bf5 VFED..C.. ......ID 64,256-1376,448 #7f070072 app:id/search_button}"
 mBackgroundTintHelper = {AppCompatBackgroundHelper@9792} 
 mTextHelper = {AppCompatTextHelper@9793} 
 mIsThemeDeviceDefault = false
 HOVER_INTERVAL = 300
 SEC_CLIPBOARD_DISABLED = 0
 SEC_CLIPBOARD_ENABLED = 1
 SEC_CLIPBOARD_UNKNOWN = -1
 TOUCH_DELTA = 12.0
 mActionModeFlags = 241664
 mAllowTransformationLengthChange = false
 mAttachedWindow = false
 mAutoLinkMask = 0
 mAutoSizeMaxTextSizeInPx = -1.0
 mAutoSizeMinTextSizeInPx = -1.0
 mAutoSizeStepGranularityInPx = -1.0
 mAutoSizeTextSizesInPx = {int[0]@9725} 
 mAutoSizeTextType = 0
 mBoring = {BoringLayout$Metrics@9794} "FontMetricsInt: top=-60 ascent=-52 descent=14 bottom=16 leading=0 width=441"
 mBreakStrategy = 0
 mBufferType = {TextView$BufferType@9727} "NORMAL"
 mButtonShapeAlpha = 0
 mButtonShapeColor = -570425344
 mButtonShapeLuminance = 0.0
 mButtonShapeOutlineRadius = 0
 mButtonShapeOutlineStrokeBottom = 0
 mButtonShapeOutlineStrokeDisabled = 0
 mButtonShapeOutlineStrokeEnabled = 0
 mButtonShapeOutlineStrokeHorizontal = 0
 mButtonShapeOutlineStrokeTop = 0
 mButtonShapePaint = null
 mButtonShapeRect = null
 mButtonShapeSettingEnabled = false
 mButtonShapeTextColor = null
 mButtonShapeTextColorDark = 0
 mButtonShapeTextColorLight = 0
 mCanPaste = false
 mCanTextMultiSelection = false
 mChangeWatcher = null
 mChangedSelectionBySIP = false
 mCharWrapper = null
 mClipboardChangeListener = null
 mClipboardDataFormat = 1
 mCoverManager = null
 mCurHintTextColor = 1627389952
 mCurTextColor = -570425344
 mCurrentSpellCheckerLocaleCache = null
 mCursorDrawable = null
 mCursorDrawableRes = 17304300
 mDPIMaxLength = -1
 mDPITextBuffer = null
 mDeferScroll = -1
 mDesiredHeightAtMeasure = 192
 mDeviceProvisionedState = 0
 mDisplayText = null
 mDrawStrikeAnimationValue = 0.0
 mDrawTextStrikeAnimator = null
 mDrawables = null
 mEditableFactory = {Editable$Factory@9728} 
 mEditor = null
 mEllipsisKeywordCount = -1
 mEllipsisKeywordStart = -1
 mEllipsize = null
 mEnableLinkPreview = false
 mEnableMultiSelection = true
 mFakeBold = {Boolean@9729} false
 mFilters = {InputFilter[0]@9730} 
 mFlagForGlobalLayout = false
 mFreezesText = false
 mGlobalLayoutListener = null
 mGravity = 17
 mHasPresetAutoSizeValues = false
 mHighlightColor = 1728004225
 mHighlightPaint = {Paint@9795} 
 mHighlightPath = null
 mHighlightPathBogus = true
 mHint = null
 mHintBoring = null
 mHintLayout = null
 mHintTextColor = {ColorStateList@9732} "ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[16842910, 16842919], []]mColors=[-1979711488, 1627389952]mDefaultColor=1627389952}"
 mHorizontallyScrolling = false
 mHoverEnterTime = -1
 mHoverExitTime = -1
 mHoveredSpan = null
 mHyphenationFrequency = 0
 mIncludePad = true
 mIsButtonShapeTarget = false
 mIsDebugTextClock = false
 mIsSecClipboardEnabled = -1
 mIsShowingLinkPreview = false
 TextView.mIsThemeDeviceDefault = false
 mIsThemeDeviceDefaultDark = false
 mIsTouchDown = false
 mJustificationMode = 0
 mKeycodeDpadCenterStatus = false
 mLastLayoutDirection = 0
 mLastScroll = 0
 mLastValueSentToAutofillManager = null
 mLayout = {BoringLayout@9796} 
 mLineIsDrawed = false
 mLinkTextColor = {ColorStateList@9734} "ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[]]mColors=[-49023]mDefaultColor=-49023}"
 mLinksClickable = true
 mListenerChanged = false
 mListeners = null
 mLocalesChanged = false
 mMarquee = null
 mMarqueeFadeMode = 0
 mMarqueeRepeatLimit = 3
 mMaxMode = 1
 mMaxWidth = 2147483647
 mMaxWidthMode = 2
 mMaximum = 2147483647
 mMinMode = 2
 mMinWidth = 352
 mMinWidthMode = 2
 mMinimum = 192
 mMovement = null
 mMultiHighlightColor = -1728022343
 mMultiHighlightPaint = null
 mMultiSelectPopupWindow = {MultiSelectPopupWindow@9735} 
 mNeedsAutoSizeText = false
 mOldMaxMode = 1
 mOldMaximum = 2147483647
 mPasteEventListener = null
 mPenSelectionController = null
 mPreDrawListenerDetached = false
 mPreDrawRegistered = false
 mPrecomputed = null
 mPreventDefaultMovement = false
 mRestartMarquee = false
 mRestrictionPolicy = null
 mSavedHintLayout = null
 mSavedLayout = {BoringLayout@9796} 
 mSavedMarqueeModeLayout = null
 mScroller = null
 mSemClipboardManager = null
 mShadowColor = 0
 mShadowDx = 0.0
 mShadowDy = 0.0
 mShadowRadius = 0.0
 mSingleLine = false
 mSkipUpdateDisplayText = false
 mSoftInputEnabled = true
 mSpacingAdd = 0.0
 mSpacingMult = 1.0
 mSpannable = null
 mSpannableFactory = {Spannable$Factory@9736} 
 mStrikeThroughPaint = null
 mStylusEventListener = null
 mTempRect = null
 mTempTextPaint = null
 mText = "Search for Device"
 mTextClassificationContext = null
 mTextClassificationSession = null
 mTextClassifier = null
 mTextColor = {ColorStateList@9738} "ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[-16842910], []]mColors=[1107296256, -570425344]mDefaultColor=-570425344}"
 mTextDir = {TextDirectionHeuristics$TextDirectionHeuristicInternal@9739} 
 mTextEditSuggestionContainerLayout = 17367391
 mTextEditSuggestionHighlightStyle = 16974826
 mTextEditSuggestionItemLayout = 17367393
 mTextEffect = {SFText@9798} 
 mTextEffectFontFamily = "sans-serif-medium"
 mTextEffectLines = 0
 mTextId = 2131427338
 mTextOperationUser = null
 mTextPaint = {TextPaint@9799} 
 mTextSelectHandle = null
 mTextSelectHandleLeft = null
 mTextSelectHandleLeftRes = 17304305
 mTextSelectHandleRes = 17304307
 mTextSelectHandleRight = null
 mTextSelectHandleRightRes = 17304309
 mTextSetFromXmlOrResourceId = true
 mTextStrikeThroughEnabled = false
 mToolType = 0
 mTransformation = null
 mTransformed = "Search for Device"
 mUseDisplayText = false
 mUseFallbackLineSpacing = true
 mUseInternationalizedInput = true
 mUserSetTextScaleX = false
 mWordIteratorForMultiSelection = null
 mhasMultiSelection = false
 isPenSideButton = false
 mAccessibilityCursorPosition = -1
 mAccessibilityDelegate = null
 mAccessibilityPaneTitle = null
 mAccessibilityTraversalAfterId = -1
 mAccessibilityTraversalBeforeId = -1
 mAccessibilityViewId = 7
 mAnimator = null
 mAppRespTracker = null
 mAttachInfo = {View$AttachInfo@9743} 
 mAttributeResolutionStacks = null
 mAttributeSourceResId = null
 mAttributes = null
 mAutofillHints = null
 mAutofillId = null
 mAutofillViewId = -1
 mBackground = {RippleDrawable@9800} 
 mBackgroundRenderNode = {RenderNode@9801} 
 mBackgroundResource = 0
 mBackgroundSizeChanged = false
 mBackgroundTint = null
 mBixbyTouchFoundText = null
 mBottom = 448
 mBottomLeftRound = null
 mBottomLeftRoundColor = 0
 mBottomRightRound = null
 mBottomRightRoundColor = 0
 mCachedContentCaptureSession = null
 mCachingFailed = false
 mClipBounds = null
 mContentCaptureSession = null
 mContentDescription = null
 mContext = {MainActivity@9661} 
 mCurrentAnimation = null
 mDefaultFocusHighlight = null
 mDefaultFocusHighlightCache = null
 mDefaultFocusHighlightEnabled = true
 mDefaultFocusHighlightSizeChanged = true
 mDefaultRoundedCornerColor = 0
 mDeviceRadius = 0
 mDirectPenInput = null
 mDisablePenGestureforfactorytest = true
 mDrawableState = {int[4]@9802} 
 mDrawingCache = null
 mDrawingCacheBackgroundColor = 0
 mExplicitStyle = 0
 mExtraPaddingBottomForPreference = 0
 mFloatingTreeObserver = null
 mForegroundInfo = null
 mFrameMetricsObservers = null
 mGhostView = null
 mHasPerformedLongPress = false
 mHorizontalScrollbarPosition = 0
 mHoverPopup = null
 mHoverPopupToolTypeByApp = 0
 mHoverPopupType = 0
 mHoveringTouchDelegate = false
 mID = 2131165298
 mIgnoreNextUpEvent = false
 mImageFilterBridge = null
 mInContextButtonPress = false
 mInputEventConsistencyVerifier = null
 mIsAllowedPokeDrawLock = false
 mIsDirectPenInputEnabled = false
 mIsSetFingerHoveredInAppWidget = true
 mKeyedTags = null
 mLabelForId = -1
 mLastIsOpaque = false
 mLayerPaint = null
 mLayerType = 0
 mLayoutInsets = null
 mLayoutParams = {LinearLayout$LayoutParams@9803} 
 mLeft = 64
 mLeftPaddingDefined = false
 mListenerInfo = {View$ListenerInfo@9804} 
 mLongClickX = NaN
 mLongClickY = NaN
 mMatchIdPredicate = null
 mMatchLabelForPredicate = null
 mMeasureCache = {LongSparseLongArray@9805} "{4611691655571966032=5634997092544}"
 mMeasuredHeight = 192
 mMeasuredWidth = 1312
 mMinHeight = 192
 View.mMinWidth = 352
 mNeededToChangedScrollBarPosition = false
 mNestedScrollingParent = null
 mNextClusterForwardId = -1
 mNextFocusDownId = -1
 mNextFocusForwardId = -1
 mNextFocusLeftId = -1
 mNextFocusRightId = -1
 mNextFocusUpId = -1
 mOldHeightMeasureSpec = -2147481520
 mOldWidthMeasureSpec = 1073743136
 mOutlineProvider = {ViewOutlineProvider$1@9750} 
 mOverScrollMode = 1
 mOverlay = null
 mPaddingBottom = 40
 mPaddingLeft = 48
 mPaddingRight = 48
 mPaddingTop = 40
 mParent = {LinearLayout@9751} "android.widget.LinearLayout{dab43e2 V.E...... .......D 0,0-1440,2448}"
 mPendingCheckForLongPress = null
 mPendingCheckForTap = null
 mPerformClick = null
 mPointerIcon = null
 mPointerIconForMouse = null
 mPointerIconForStylus = null
 mPrivateFlags = -2128607216
 mPrivateFlags2 = 1611867688
 mPrivateFlags3 = 537395220
 mRecreateDisplayList = false
 mRenderNode = {RenderNode@9806} 
 mRenderNodeImageFilter = null
 mRenderNodeImageFilterClipRects = {ArrayList@9807}  size = 0
 mResources = {Resources@9707} 
 mRight = 1376
 mRightPaddingDefined = false
 mRoundRadius = -1
 mRoundScrollbarRenderer = null
 mRoundedCornerBounds = {Rect@9808} "Rect(0, 0 - 0, 0)"
 mRoundedCornerMode = 0
 mRoundedCornerRadius = 0
 mRunQueue = null
 mScrollBarPositionPadding = 0
 mScrollCache = null
 mScrollIndicatorDrawable = null
 mScrollX = 0
 mScrollY = 0
 mScrollbarVerticalPadding = 0
 mSemHorizontalScrollbarRect = {Rect@9809} "Rect(0, 0 - 0, 0)"
 mSemOffsetRequesterBounds = null
 mSemOffsetRequesterExpirer = null
 mSemOffsetRequesterTrimer = null
 mSemOnAddRemoveListener = null
 mSemSFState = 0
 mSemScrollingByScrollbar = false
 mSemScrollingVertical = true
 mSemVerticalChildOffset = 0
 mSemVerticalScrollbarRect = {Rect@9810} "Rect(0, 0 - 0, 0)"
 mSemViewFlags = 0
 mSendViewScrolledAccessibilityEvent = null
 mSendingHoverAccessibilityEvents = false
 mSmartClipDataExtractionListener = null
 mSmartClipDataTag = null
 mSourceLayoutId = 2131296284
 mStartActivityRequestWho = null
 mStateListAnimator = {StateListAnimator@9811} 
 mSystemUiVisibility = 0
 mTag = null
 mTempNestedScrollConsumed = null
 mTooltipInfo = null
 mTop = 256
 mTopLeftRound = null
 mTopLeftRoundColor = 0
 mTopRightRound = null
 mTopRightRoundColor = 0
 mTouchDelegate = null
 mTouchSlop = 32
 mTransformationInfo = null
 mTransientStateCount = 0
 mTransitionName = null
 mUnscaledDrawingCache = null
 mUnsetPressedState = null
 mUserPaddingBottom = 40
 mUserPaddingEnd = -2147483648
 mUserPaddingLeft = 48
 mUserPaddingLeftInitial = 48
 mUserPaddingRight = 48
 mUserPaddingRightInitial = 48
 mUserPaddingStart = -2147483648
 mVerticalScrollFactor = 0.0
 mVerticalScrollbarPosition = 0
 mViewFlags = 402669569
 mVisibilityChangeForAutofillHandler = null
 mWindowAttachCount = 1
 shadow$_klass_ = {Class@9494} "class android.support.v7.widget.AppCompatButton"
 shadow$_monitor_ = -1961022475
mPSoCCapSenseLedService = null
ian.templeton
  • 59
  • 1
  • 3

3 Answers3

0

maybe you need to scan and stop the scanning before binding the service. my ble scanning and binding is as below:

final BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
ScanSettings settings = new ScanSettings.Builder()
    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
    .build();
List<ScanFilter> filters = new ArrayList<>();
new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        scanner.stopScan(scanCallback);
        bindService(new Intent(ControlActivity.this, BLEService.class), 
            mServiceConnection, BIND_AUTO_CREATE);

            }
        }
    }, 3500);

    scanner.startScan(filters, settings, scanCallback);

and for the connection callback:

private final ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        bleService = ((BLEService.LocalBinder) service).getService();
        try {
            bleService.connect(device mac);
        } catch (Exception e) {
            updateText("Connection Disconnected...");
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        bleService = null;
    }
};
kabayaba
  • 195
  • 1
  • 13
0

After discussing it with my professor we discovered the scan, connect, and discoverSevices callbacks were being executed near simultaneously and not sequentially. To avoid the simultaneous execution I delayed the callbacks and after extensive trial and error, these were the optimal delays I have found.

    public void startBluetooth(View view) {

        /** Find BLE service and adapter */
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

        /** Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
        // fire an intent to display a dialog asking the user to grant permission to enable it. */
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BLE);
        }

        /** Start the BLE Service */
        Log.d(TAG, "Starting BLE Service");
        Intent gattServiceIntent = new Intent(this, PSoCCapSenseLEDService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);


        /** Disable the start button and turn on the search  button */
        start_button.setEnabled(false);
        search_button.setEnabled(true);
        Log.d(TAG, "Bluetooth is Enabled");

        new CountDownTimer(15, 1000) {
            public void onFinish() {
                // When timer is finished
                // Execute your code here
                mPSoCCapSenseLedService.scan();
            }

            public void onTick(long millisUntilFinished) {
                // millisUntilFinished    The amount of time until finished.
            }
        }.start();

// roughly 65ms after scanning
        new CountDownTimer(80, 1000) {
            public void onFinish() {
                // When timer is finished
                // Execute your code here
                mPSoCCapSenseLedService.connect();
            }

            public void onTick(long millisUntilFinished) {
                // millisUntilFinished    The amount of time until finished.
            }
        }.start();

// needs to be roughly 260ms after connection
        new CountDownTimer(340, 1000) {
            public void onFinish() {
                // When timer is finished
                // Execute your code here
                mPSoCCapSenseLedService.discoverServices();
            }

            public void onTick(long millisUntilFinished) {
                // millisUntilFinished    The amount of time until finished.
            }
        }.start();
ian.templeton
  • 59
  • 1
  • 3
0

Sorry to say this but what you are doing in your answer at https://stackoverflow.com/a/60694898/556495 is fundamentally wrong. Don't use arbitrary timers like this. It will definitely fail in many cases since the radio timings can differ a lot depending on the environment.

The BLE API in Android is callback based. That means the scan results are delivered as ScanCallbacks. When the callback is called and the device is one you want to connect to, THAT'S when you connect.

And when you connect you supply a BluetoothGattCallback and implement the onConnectionStateChange method. If the state indicates the device is now connected, THAT'S when you call discoverServices. The service discovery is not completed earlier than when the onServicesDiscovered callback arrives, so first at this point you can start the GATT transactions.

And remember that you can only have one outstanding GATT operation at a time (you need to wait for the corresponding callback before you can execute another one).

Emil
  • 16,784
  • 2
  • 41
  • 52