简体   繁体   中英

BLE Scanner only shows one record

I am working on a Bluetooth Scanner in android studio. I am still learning so i'm terribly sorry for all the rooky mistakes. I had it working a while ago, but couldn't get the UUID from a device. So I searched and searched and finally I had something working. But now the problem is that there is only one BLE device after a scan. The list doesn't expand. If I use another scanning app I'm finding multiple devices.

Your help would be much appreciated and any feedback on my rooky code is more then welcome!

PS: please know that i used some code I've found online, so if there is anything useless or really weird, please inform me..

public class Scanner_BTLE {

private MainActivity ma;

private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;

private long scanPeriod;
private int signalStrength;


public Scanner_BTLE(MainActivity mainActivity, long scanPeriod, int signalStrength) {
    ma = mainActivity;

    mHandler = new Handler();

    this.scanPeriod = scanPeriod;
    this.signalStrength = signalStrength;

    final BluetoothManager bluetoothManager =
            (BluetoothManager) ma.getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
}

// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {

            @Override
            public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {

                final int new_rssi = rssi;

                int startByte = 2;
                boolean patternFound = false;
                while (startByte <= 5) {
                    if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && //Identifies an iBeacon
                            ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { //Identifies correct data length
                        patternFound = true;
                        break;
                    }
                    startByte++;
                }

                if (patternFound) {
                    //Convert to hex String
                    byte[] uuidBytes = new byte[16];
                    System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);
                    String hexString = bytesToHex(uuidBytes);

                    //UUID detection
                    final String uuid = hexString.substring(0, 8) + "-" +
                            hexString.substring(8, 12) + "-" +
                            hexString.substring(12, 16) + "-" +
                            hexString.substring(16, 20) + "-" +
                            hexString.substring(20, 32);

                    // major
                    final int major = (scanRecord[startByte + 20] & 0xff) * 0x100 + (scanRecord[startByte + 21] & 0xff);

                    // minor
                    final int minor = (scanRecord[startByte + 22] & 0xff) * 0x100 + (scanRecord[startByte + 23] & 0xff);


                    if (rssi > signalStrength) {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                ma.addDevice(device, new_rssi, scanRecord, major, minor, uuid);
                            }
                        });
                    }
                }
            }
        }

        ;


public boolean isScanning() {
    return mScanning;
}

public void start() {
    if (!Utils.checkBluetooth(mBluetoothAdapter)) {
        Utils.requestUserBluetooth(ma);
        ma.stopScan();
    } else {


            scanLeDevice(true);

    }
}

public void stop() {
    scanLeDevice(false);
}

// If you want to scan for only specific types of peripherals,
// you can instead call startLeScan(UUID[], BluetoothAdapter.LeScanCallback),
// providing an array of UUID objects that specify the GATT services your app supports.


private void scanLeDevice(final boolean enable) {

    if (enable && !mScanning) {
        Utils.toast(ma.getApplicationContext(), "Starting BLE scan...");

        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Utils.toast(ma.getApplicationContext(), "Stopping BLE scan...");

                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);

                ma.stopScan();
            }
        }, scanPeriod);

        mScanning = true;

            mBluetoothAdapter.startLeScan(mLeScanCallback);


    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}




}

BTLE_DEVICE

public class BTLE_Device {

private BluetoothDevice bluetoothDevice;
private int rssi;

private String uuid;
private int major;
private int minor;

public BTLE_Device(BluetoothDevice bluetoothDevice) {
    this.bluetoothDevice = bluetoothDevice;
}



public void setRSSI(int rssi) {
    this.rssi = rssi;
}

public int getRSSI() {
    return rssi;
}



public String getUuid() {
    return uuid;
}

public void setUuid(String uuid) {
    this.uuid = uuid;
}

public int getMajor() {
    return major;
}

public void setMajor(int major) {
    this.major = major;
}

public int getMinor() {
    return minor;
}

public void setMinor(int minor) {
    this.minor = minor;
}
}

LIST ADAPTER (no idea if i'm doing this right :) )

public class ListAdapter_BTLE_Devices extends ArrayAdapter<BTLE_Device> {

Activity activity;
int layoutResourceID;
ArrayList<BTLE_Device> devices;

public ListAdapter_BTLE_Devices(Activity activity, int resource, ArrayList<BTLE_Device> objects) {
    super(activity.getApplicationContext(), resource, objects);
    this.activity = activity;
    layoutResourceID = resource;
    devices = objects;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        LayoutInflater inflater =
                (LayoutInflater) activity.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(layoutResourceID, parent, false);
    }

    BTLE_Device device = devices.get(position);

    String rssi = String.valueOf (device.getRSSI());
    String major = String.valueOf (device.getMajor());
    String minor = String.valueOf (device.getMinor ());
    String uuid = device.getUuid ();

    TextView tv_major = (TextView)convertView.findViewById (R.id.tv_major);
    TextView tv_minor = (TextView)convertView.findViewById (R.id.tv_minor);
    TextView tv_uuid = (TextView)convertView.findViewById (R.id.tv_uuid);
    TextView tv_rssi = (TextView)convertView.findViewById (R.id.tv_rssi);

    tv_major.setText (major);
    tv_minor.setText (minor);
    tv_uuid.setText (uuid);
    tv_rssi.setText (rssi);

    return convertView;
}
}

And finally my Main Activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {

//INITIALIZE VARIABLES
private final static String           TAG                               = MainActivity.class.getSimpleName ( );
public static final  int              REQUEST_ENABLE_BT                 = 1;
private HashMap <String, BTLE_Device> mBTDevicesHashMap;
private ArrayList <BTLE_Device>       mBTDevicesArrayList;
private ListAdapter_BTLE_Devices      adapter;
private Button                        btn_addIncident;
private Button                        btn_Scan;
private Button                        btn_incidentlist;
private Button                        btn_scanMyBeacon;
private BroadcastReceiver_BTState     mBTStateUpdateReceiver;
private Scanner_BTLE                  mBTLeScanner;
private static final int              PERMISSION_REQUEST_COARSE_LOCATION    = 456;
private Realm                         realm;


@Override
//ONCREATE
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //CHECK IF BL IS SUPPORTED ON DEVICE
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Utils.toast(getApplicationContext(), "BLE not supported");
        finish();
    }
    //REQUEST PERIMISSIONS ( BLUETOOTH & GPS )
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
    }
    //INITIALIZE
    mBTStateUpdateReceiver = new BroadcastReceiver_BTState(getApplicationContext());
    mBTLeScanner = new Scanner_BTLE(this, 7500, -105);
    mBTDevicesHashMap = new HashMap<>();
    mBTDevicesArrayList = new ArrayList<>();
    adapter = new ListAdapter_BTLE_Devices(this, R.layout.btle_device_list_item, mBTDevicesArrayList);
    ListView listView = new ListView(this);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(this);
    ((ScrollView) findViewById(R.id.scrollView)).addView(listView);

    //BUTTONS TO VARIABLE
    btn_scanMyBeacon = (Button) findViewById(R.id.btn_scanMyBeacon);
    btn_Scan = (Button) findViewById(R.id.btn_scan);
    btn_incidentlist = (Button) findViewById(R.id.btn_incident_list_sort);
    btn_addIncident = (Button) findViewById(R.id.btn_addIncident);


    //ONCLICKLISTENERS
    btn_Scan.setOnClickListener(this);
    btn_scanMyBeacon.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startScan();
        }
    });
    btn_incidentlist.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent listIntent = new Intent(MainActivity.this,IncidentListActivity.class);
            MainActivity.this.startActivity(listIntent);
        }
    });
    btn_addIncident.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent myIntent = new Intent(MainActivity.this, Add_Incident.class);
            MainActivity.this.startActivity(myIntent);
        }
    });

    //REALM
    try {
        realm = Realm.getDefaultInstance ( ); // opens "myrealm.realm"
    }
    catch (Exception e) {
        RealmConfiguration config = new RealmConfiguration.Builder ()
                .deleteRealmIfMigrationNeeded ()
                .build ();
        realm.getInstance (config);
    }
}
@Override
//ONSTART
protected void onStart() {
    super.onStart();

    registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
@Override
//ONRESUME
protected void onResume() {
    super.onResume();

}
@Override
//ONPAUSE
protected void onPause() {
    super.onPause();

    stopScan();
}
@Override
//ONSTOP
protected void onStop() {
    super.onStop();

    unregisterReceiver(mBTStateUpdateReceiver);
    stopScan();
}
@Override
//ONDESTROY
public void onDestroy() {
    super.onDestroy();
    realm.close();
}
@Override
//BLUETOOTH CHECK
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    // Check which request we're responding to
    if (requestCode == REQUEST_ENABLE_BT) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
             Utils.toast(getApplicationContext(), "Thank you for turning on Bluetooth");
        } else if (resultCode == RESULT_CANCELED) {
            Utils.toast(getApplicationContext(), "Please turn on Bluetooth");
        }
    }
}

@Override
//ONCLICK SCAN BUTTON
public void onClick(View v) {
//Called when the scan button is clicked. v= clicked view
    switch (v.getId()) {

        case R.id.btn_scan:
            Utils.toast(getApplicationContext(), "Scan Button Pressed");

            if (!mBTLeScanner.isScanning()) {
                startScan();

            } else {
                stopScan();
            }

            break;
        default:
            break;
    }
}

//ADD DEVICE
/**
 * Adds a device to the ArrayList and Hashmap that the ListAdapter is keeping track of.
 *
 * @param device the BluetoothDevice to be added
 * @param rssi   the rssi of the BluetoothDevice
 */
public void addDevice(BluetoothDevice device, int rssi, byte[] scanRecord, int major, int minor, String uuid) {

    Log.d ("first add","Device"+ device.getAddress ()+"rssi" +rssi+"uuid"+uuid );
    Log.d("HashMap",""+mBTDevicesHashMap.size());
    Log.d("ArrayList",""+mBTDevicesArrayList.size());
    if (!mBTDevicesHashMap.containsKey(uuid)) {
        BTLE_Device btleDevice = new BTLE_Device(device);
        btleDevice.setRSSI(rssi);

        mBTDevicesHashMap.put(uuid, btleDevice);
        mBTDevicesArrayList.add(btleDevice);
    } else {
        BTLE_Device current = mBTDevicesHashMap.get(uuid);
        current.setRSSI(rssi);
        current.setMajor(major);
        current.setMinor(minor);
        current.setUuid(uuid);
    }
    Log.d("HashMapAfter",""+mBTDevicesHashMap.size());
    Log.d("ArrayListAfter",""+mBTDevicesArrayList.size());

    adapter.notifyDataSetChanged();
}

//START SCAN
/**
 * Clears the ArrayList and Hashmap the ListAdapter is keeping track of.
 * Starts Scanner_BTLE.
 * Changes the scan button text.
 */
public void startScan() {
    btn_Scan.setText("Scanning...");

    mBTDevicesArrayList.clear();
    mBTDevicesHashMap.clear();

    adapter.notifyDataSetChanged();


        mBTLeScanner.start();


}

//STOP SCAN
/**
 * Stops Scanner_BTLE
 * Changes the scan button text.
 */
public void stopScan() {
    btn_Scan.setText("Scan Again");

    mBTLeScanner.stop();

    for(int i=0; i<mBTDevicesArrayList.size();i++){
        System.out.println (mBTDevicesArrayList.get(i).getUuid() );
    }
}



/**
 * Called when an item in the ListView is clicked.
 */
 @Override
 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 System.out.println ( );
}
}

Jesper, you are sure that next to you there are several devices that meet the bottom condition

if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && 
                        ((int) scanRecord[startByte + 3] & 0xff) == 0x15)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM