I am building an android app to connect and read data from an Arduino-based BLE device. I was able to find and connect to the device, but for some reason the onServicesDiscovered() callback function never gets called no matter how hard I try. I have already tried waiting 600 milliseconds before discovering, and even 1.5 seconds, I made sure that the discoverServices() command is running on the UI thread, and have redone the Bluetooth code numerous times. I was able to do this successfully before, and the function would be called, but I wanted to put all of the Bluetooth code in its own separate class file to clean up my main activity file, and I did so without creating a backup and this was where my problem started. So then I tried to redo it again in my main file, but to no avail.

Edit: The original code that I published didn't work anyway, so this is the updated code but with the same error.

Here is my code (this is my main activity file):

```java
package com.example.androidrf;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;

import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.UUID;

import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;

public class MainActivity extends AppCompatActivity {
    public TabLayout tabLayout;
    public ViewPager2 viewPager;
    public TextView connectionWarning;

    // Bluetooth Variables
    BluetoothManager bluetoothManager;

    BluetoothAdapter bluetoothAdapter;

    private static final int REQUEST_ENABLE_BT = 1;

        // UUID's
    private String arduinoName;
    private String serviceId;
    private String ledCharacteristicId;
    private String numberCharacteristicId;
    private UUID serviceUUID;
    private UUID ledCharUUID;
    private UUID numCharUUID;

        // Scan Settings
    private ScanFilter scanFilter;
    private ScanSettings scanSettings;

    // GATT, Characteristics, and Services
    private BluetoothGatt gatt;
    private BluetoothGattService service;
    private BluetoothGattCharacteristic ledChar;
    private BluetoothGattCharacteristic numberChar;

    // Scanning Related Code
    private final BluetoothLeScanner bluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
    private boolean mScanning;
    private final Handler handler = new Handler();

    // Stops scanning after 10 seconds.
    private static final long SCAN_PERIOD = 10000;

    private void scanDevices(boolean forceStop) {
        if (forceStop) {
            mScanning = false;
            bluetoothLeScanner.stopScan(scanCallback);
        }
    }

    private void scanDevices() {
        if (!mScanning) {
            // Stops scanning after a pre-defined scan period.
            handler.postDelayed(() -> {
                if (!mScanning) return;
                mScanning = false;
                bluetoothLeScanner.stopScan(scanCallback);
            }, SCAN_PERIOD);
            if (deviceFound) return;
            mScanning = true;
            bluetoothLeScanner.startScan(Collections.singletonList(scanFilter), scanSettings, scanCallback);
        } else {
            mScanning = false;
            bluetoothLeScanner.stopScan(scanCallback);
        }
    }

    // Scan Callback
    private boolean deviceFound;

    private final ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            if (deviceFound) {
                bluetoothLeScanner.flushPendingScanResults(this);
                if (mScanning) scanDevices(true);
                return;
            }
            if (result.getScanRecord().getDeviceName().equals(arduinoName)) {
                deviceFound = true;
                new Handler(Looper.getMainLooper()).postDelayed(() -> gatt = result.getDevice().connectGatt(getBaseContext(), false, gattCallback, TRANSPORT_LE), 600);
                //gatt.connect();
            }
        }
    };

    // GATT Callback
    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.d("Gatt Services", "Status: " + status + ", newState: " + newState);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothGatt.STATE_CONNECTED) {
                    new Handler(Looper.getMainLooper()).postDelayed(() -> {
                        Log.d("Gatt Services", "Discovering Services");
                        runOnUiThread(gatt::discoverServices);
                    }, 600);
                }
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Log.d("Gatt Characteristics", "Success");
            if (status == BluetoothGatt.GATT_SUCCESS) {
                ledChar = gatt.getService(serviceUUID).getCharacteristic(ledCharUUID);
                numberChar = gatt.getService(serviceUUID).getCharacteristic(numCharUUID);
                gatt.setCharacteristicNotification(numberChar, true);

            }
        }

//      @Override
//      public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//          super.onCharacteristicRead(gatt, characteristic, status);
//      }
//
//      @Override
//      public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//          super.onCharacteristicWrite(gatt, characteristic, status);
//      }
//
//      @Override
//      public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//          super.onCharacteristicChanged(gatt, characteristic);
//      }
//
//      @Override
//      public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
//          super.onReadRemoteRssi(gatt, rssi, status);
//      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        connectionWarning = findViewById(R.id.warningLabel);

        //Bluetooth ------------------------------------------------------------------------------------------

        bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();

        arduinoName = getResources().getString(R.string.arduino_name);
        serviceId = getResources().getString(R.string.service_id);
        ledCharacteristicId = getResources().getString(R.string.led_char_id);
        numberCharacteristicId = getResources().getString(R.string.num_char_id);

        serviceUUID = UUID.fromString(serviceId);
        ledCharUUID = UUID.fromString(ledCharacteristicId);
        numCharUUID = UUID.fromString(numberCharacteristicId);

        scanFilter = new ScanFilter.Builder().setDeviceName(arduinoName).build();
        scanSettings = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
                //.setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
                .build();

        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        scanDevices();

        //ViewPager ------------------------------------------------------------------------------------------
        sectionsPagerAdapter SectionsPagerAdapter = new sectionsPagerAdapter(this);
        viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(SectionsPagerAdapter);

        // Tab Layout ----------------------------------------------------------------------------------------
        tabLayout = findViewById(R.id.tabs);
        new TabLayoutMediator(tabLayout, viewPager, true, true, (tab, position) -> {
            String text = "";

            switch(position) {
                case 0:
                    text = getString(R.string.tab_text_1);
                    break;
                case 1:
                    text = getString(R.string.tab_text_2);
                    break;
            }
            tab.setText(text);
        }).attach();
    }

    private static class sectionsPagerAdapter extends FragmentStateAdapter {
        public sectionsPagerAdapter(FragmentActivity fa) {
            super(fa);
        }

        @NotNull
        @Override
        public Fragment createFragment(int position) {
            Fragment fragment = null;
            switch(position) {
                case 0:
                    fragment = new HomeFragment();
                    break;
                case 1:
                    fragment = new SettingsFragment();
                    break;
            }
            return fragment;
        }

        @Override
        public int getItemCount() {
            return 2;
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (gatt == null) return;
        gatt.close();
        gatt = null;
    }
}

```