I'm trying to connect my Beacons to the Gattservice. In the Callback onConnectionStateChange, It's always failing and im getting the
statuscodes 133 and 257.
Somehwere was written that 133 stands for to many connections. In my code there are lines with gatt.disconnect().
I don't know how to fix it, because all other gattexamples are the same. I'm working with the Android 6.0.1 Version and the API 23, if it's important to find the error.
Here's my code:
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(status == BluetoothGatt.GATT_SUCCESS) {
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
mBleDevices.add(gatt.getDevice());
Log.i("Beacons", "STATE_CONNECTED");
runOnUiThread(new Runnable() {
#Override
public void run() {
mBluetoothGatt.discoverServices();
}
});
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("Beacons", "STATE_DISCONNECTED");
mBleDevices.remove(gatt.getDevice());
mBluetoothGatt.disconnect();
mBluetoothGatt = null;
break;
default:
Log.e("Beacons", "STATE_OTHER");
}
} else {
Log.e("Beacons", "ERROR WITH CONNECTING " + status);
mBleDevices.remove(gatt.getDevice());
}
}
My ScanCallback looks like this:
public void onScanResult(int callbackType, ScanResult result) {
runOnUiThread(new Runnable() {
#Override
public void run() {
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
});
}
And starting connection like this:
runOnUiThread(new Runnable() {
#Override
public void run() {
mBluetoothGatt = btDevice.connectGatt(getApplicationContext(), true, connectCallback);
}
});
The connectCallback causes then onConnectionStateChange function.
Thank you for your help!
On some Android devices, I see a 133 error on connect if the Android phone has not been paired (bonded) with the peripheral before. If I go to Settings -> Bluetooth at the same time as the app is trying to connect in the background, the connection works. (Strangely, you do not need to do anything on the screen, it just needs to be up.) Once this succeeds the first time, the error is gone forever.
I'm guessing this is a security restriction, but I have not figured the proper way to elegantly address it.
I had to specify the transport parameter in the call to fix this. It's an optional 4th paramater to specify it's a BLE device.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback, 2);
https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback,%20int)
try this:For start scan:
private void scanLeDevice(final boolean enable) {
if (enable) {
ParcelUuid uuid = ParcelUuid.fromString("Your Beacon Service UUID");
ScanFilter scanFilter = new ScanFilter.Builder().setServiceUuid(uuid).build();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(0)
.build();
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(Collections.singletonList(scanFilter), settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
For scanCallBack
private ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
#Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
Connect the device
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
mGatt = device.connectGatt(this, false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
gattcallback
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
Then override onServicesDiscovered method.
133 is a generic error and means nothing at all except that the connection failed. It can mean many different things. You need to look at Logcat and figure out why it didn't connect or the hci snoop log.
Related
I'm building an app that should to connect a BLE device and download all the information that this device has storage in your flash memory.
So I'm building this code:
This is the Timer that I use to download ALL the information every X minutes:
TimerTask timerTask = new TimerTask() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void run() {
valore = true;
int conta = 0;
while(valore){
conta++;
if (currDevice != null) {
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
}else{
//provo a ricollegarmi al dispositivo probabile, abbia perso la connessione con esso
scanLeDevice(true);
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
This is the method that I use to connect at BLE device:
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void connectToDevice(BluetoothDevice device) {
//VERIFICO SE IL DEVICE รจ QUELLO CHE VOGLIO IO
if (mGatt == null && settingApp != null
&& device.getAddress().equals(settingApp.getAddressBleSX())) {
currDevice = device;
gattClientCallback = new GattClientCallback();
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
scanLeDevice(false);// will stop after first device detection
}
}
This is the LeScanCallback():
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Handler h = new Handler(getApplicationContext().getMainLooper());
// Although you need to pass an appropriate context
h.post(new Runnable() {
#Override
public void run() {
// Log.i("onLeScan", device.toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
connectToDevice(device);
}
}
});
}
};
This the last code to effectively download data from BLE device and storage it on SqlLite
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Handler h = new Handler(getApplicationContext().getMainLooper());
// Although you need to pass an appropriate context
h.post(new Runnable() {
#Override
public void run() {
// Log.i("onLeScan", device.toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
connectToDevice(device);
}
}
});
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback = new ScanCallback() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onScanResult(int callbackType, ScanResult result) {
// Log.i("callbackType", String.valueOf(callbackType));
// Log.i("result", result.toString());
BluetoothDevice btDevice = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
btDevice = result.getDevice();
}
connectToDevice(btDevice);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
// Log.i("ScanResult - Results", sr.toString());
}
}
#Override
public void onScanFailed(int errorCode) {
// Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private class GattClientCallback extends BluetoothGattCallback {
#SuppressLint("LongLogTag")
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
try{
super.onConnectionStateChange(gatt, status, newState);
Log.i("tag", "onConnectionStateChange newState: " + newState);
if (status == BluetoothGatt.GATT_FAILURE) {
Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
disconnectGattServer();
return;
} else if (status != BluetoothGatt.GATT_SUCCESS) {
// handle anything not SUCCESS as failure
Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
disconnectGattServer();
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
//Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i("INFO", "Disconnected from device");
disconnectGattServer();
}
}catch(Exception e){
Log.e("ON_CONNECTION_STATE_CHANGE", e.getMessage());
}
}
public void disconnectGattServer() {
valore = false;
if (mGatt != null) {
mGatt.disconnect();
mGatt.close();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status != BluetoothGatt.GATT_SUCCESS) {
// Log.i("INFO", "Device service discovery unsuccessful, status " + status);
return;
}
List<BluetoothGattCharacteristic> matchingCharacteristics =
BluetoothUtils.findCharacteristics(gatt,stringSequence);
if (matchingCharacteristics.isEmpty()) {
// Log.e("ERROR_SERVICE","Unable to find characteristics.");
return;
}else{
gatt.readCharacteristic(matchingCharacteristics.get(0));
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
SensorData mSenData = new SensorData();
mSenData.setValue(characteristic.getStringValue(0));
mSenData.setIdType(++id);
mSenData.setCharacteristic(characteristic.getUuid().toString());
mSenData.setValueTimestamp(db.getDateTime());
db.insertSensorData(mSenData);
} else {
Log.e("ERROR_SERVICE", "Characteristic read unsuccessful, status: " + status);
}
}
Now, if I try to start my application, I can download some data from BLE device as 35, 36 values. After that I received this message from onConnectionStateChange method
E/ERROR_SERVICE: Connection not GATT sucess status 128
So after this error, the timer stopped. After X minutes the method restart but I'm not able to download never error from BLE device.
So how can I download all data from BLE device every X minutes and until the BLE device have data storage in yuor memory ?
I have all the permissions granted.
I use the beaconManager. which I create like this:
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT));
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT));
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT));
beaconManager.bind(this);
OnBeaconConnect I do this:
#Override
public void onBeaconServiceConnect() {
ArrayList<Identifier> identifiers = new ArrayList<>();
// Set null to indicate that we want to match beacons with any value
identifiers.add(null);
// Represents a criteria of fields used to match beacon
try {
Region region = new Region("all-beacons-region", null, null, null);
Region region2 = new Region("de3be3ce-4770-477b-8893-0f0e5aeb9b98", null, null, null);
// Tells the BeaconService to start looking for beacons that match the passed Region object
beaconManager.startRangingBeaconsInRegion(region);
beaconManager.startRangingBeaconsInRegion(region2);
beaconManager.startMonitoringBeaconsInRegion(region);
beaconManager.startMonitoringBeaconsInRegion(region2);
} catch (RemoteException e) {
e.printStackTrace();
}
// Specifies a class that should be called each time the BeaconService gets ranging data, once per second by default
beaconManager.addRangeNotifier(this);
beaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
Log.i(TAG, "I just saw an beacon for the first time!");
}
#Override
public void didExitRegion(Region region) {
Log.i(TAG, "I no longer see an beacon");
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
Log.i(TAG, "I have just switched from seeing/not seeing beacons: " + state);
}
});
}
And didRangeBeaconsInRegion has this:
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Log.i(TAG, "The first beacon I see is about " + beacons.iterator().next().getDistance() + " meters away.");
}
}
But the monitorNotifier never gets called, and the rangeNotifier gets called, but beacons size is always 0.
Why don't I get the beacons here?
PS: I even tried hardcoding a beacon, using the UUID, but still I get nothing in monitorNotifier, and still size 0 in the range notifier
It looks to me like you set up three beacon parsers for the Eddystone formats, but you are trying to detect a beacon sending out the iBeacon format. (I say this based on the first identifier in the second region definition being a 16 byte UUID.) If this is indeed what you are trying to do, please add a beacon parser for the iBeacon format. You can find that here:
https://beaconlayout.wordpress.com/
Also, if you are trying to detect on Android 6+ make sure you have obtained location permissions otherwise you won't detect anything. See here:
https://altbeacon.github.io/android-beacon-library/requesting_permission.html
you can try this
public class BLEActivity extends ActionBarActivity {
private BluetoothAdapter mBluetoothAdapter;
private int REQUEST_ENABLE_BT = 1;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE Not Supported",
Toast.LENGTH_SHORT).show();
finish();
}
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
#Override
protected void onResume() {
super.onResume();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
if (Build.VERSION.SDK_INT >= 21) {
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<ScanFilter>();
}
scanLeDevice(true);
}
}
#Override
protected void onPause() {
super.onPause();
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
scanLeDevice(false);
}
}
#Override
protected void onDestroy() {
if (mGatt == null) {
return;
}
mGatt.close();
mGatt = null;
super.onDestroy();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_CANCELED) {
//Bluetooth not enabled.
finish();
return;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice btDevice = result.getDevice();
connectToDevice(btDevice);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
#Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
mGatt = device.connectGatt(this, false, gattCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.i("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
List<BluetoothGattService> services = gatt.getServices();
Log.i("onServicesDiscovered", services.toString());
gatt.readCharacteristic(services.get(1).getCharacteristics().get
(0));
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic
characteristic, int status) {
Log.i("onCharacteristicRead", characteristic.toString());
gatt.disconnect();
}
};
}
I'm trying to programmatically pair with Ble iBeacon using BluetoothGatt API in android.I can able to pair with Ble iBeacon up to lollipop.But i cannot pair in Marshmallow(My testing device is oneplus 3).I'm using altbeacon library for beacon scanning.
Also, i gave ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION permission in the manifest file and turned on GPS location.
private BluetoothGatt mGatt;
BluetoothAdapter baBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
baBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(myReceiver, intentFilter);
}
Here i'm sending beacon mac id
public void PairToDevice(String sMacId) {
BluetoothDevice device = baBluetoothAdapter.getRemoteDevice(sMacId);
if (mGatt == null) {
mGatt = device.connectGatt(this, false, gattCallback);
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
Log.e("gattCallback", "STATE_CONNECTED");
gatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.e("gattCallback", "STATE_DISCONNECTED");
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
}
}
Here i'm checking bonding state.Bonding state is always none in Marshmallow.But lessthan marshmallow it is working fine.
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int nState = device.getBondState();
if (nState == BluetoothDevice.BOND_BONDED) {
Log.e("Bond Information", "device bonded");
} else if (nState == BluetoothDevice.BOND_BONDING) {
Log.e("Bond Information", "device bonding");
} else if (nState == BluetoothDevice.BOND_NONE) {
Log.e("Bond Information", "bond none");
}
}
}
};
I have developed an app that it have to reconnect to a server app that is installed on a certain device. I have tested my app on some device, but on galaxy s6 with Lollipop I have some problem.
This are the combination :
client (peripherall) is installed on galaxy tab 10.1 kitkat
server (central role) is installed on galaxy s6 with lollipop
ok
client (peripherall) is installed on galaxy nexus 6 lollipop
server (central role) is installed on galaxy s6 with lollipop
ok
client (peripherall) is installed on galaxy s6 lollipop
server (central role) is installed on galaxy nexus 6 with lollipop
not working
On the last combination the connection function return me 133 status.
This is my code :
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.d("connect", "status = " + status + " newState = " + newState);
....
What is the difference between Kitkat and Lollipop ? Do I have to handle the connection in different way ?
public void new_automatization() {
automatizationInProgress = true;
Log.d("connect","new auto: si parte");
this.init();
Bluetooth.getMe().stopScan();
final String MACaddress=getDataFromPreferences("address");
final String keycode=getDataFromPreferences("unlockcode");
if(!Bluetooth.getMe().isScanning()) {
Bluetooth.getMe().startScan(new Bluetooth.ScanCallback() {
boolean deviceIsFound = false;
#Override
public void onDeviceFound(final BluetoothDevice device, int rssi,byte[] scanRecord) {
Log.d("testAlpha","dentro onDeviceFound");
if(device != null) {
String address=new String();
if(device.getName() != null) {
Log.d("testAlpha","trovato name: "+device.getName()+"mac: "+device.getAddress());
address=device.getName();
if(address.equals(MACaddress)) {
Log.d("testAlpha","mi connetto a: "+device.getName()+"mac: "+device.getAddress());
Bluetooth.getMe().stopScan();//possiamo riconnetterci
deviceIsFound=true;
setDevice(device);
unlock(keycode);
automatizationInProgress = false;
}
}
} else {
Log.i("connect","dentro onDeviceFound null");
search_ended=true;
sendMessage(DEVICE_NOT_FOUND);
automatizationInProgress = false;
}
}
});
}
}
This is the startscan and stopscan function :
#SuppressWarnings("deprecation")
public boolean startScan(ScanCallback callback, final long timeout) {
stopScan();
scanCallback = callback;
/*
if (isScanning()) {
stopScan();
return true;
}
scanCallback = callback;
// Stops scanning after a pre-defined scan period (10s).
stopTimer = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
Log.i("debug","interrupted");
return;
}
Log.i("debug","bluetooth: inizia lo stopscan()");
if(!isScanning())
return;
Log.i("debug","amgbluetooth: pre scansione");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BluetoothLeScanner scanner = bluetoothAdapter
.getBluetoothLeScanner();
scanner.stopScan(scanCallbackAfterLollipop);
scanning = false;
} else {
bluetoothAdapter.stopLeScan(scanCallbackBeforeLollipop);
scanning = false;
}
Log.i("debug","amgbluetooth:stopTimer, invio null");
if(!Thread.currentThread().isInterrupted())
scanCallback.onDeviceFound(null, 0, null);
}
});
stopTimer.start();*/
pippo.removeCallbacks(solPippo);
pippo.postDelayed(solPippo, timeout);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.i("finalT","amgbluetooth: inizia lo startscan() LL");
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
scanning = true;
scanCallbackAfterLollipop = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.d("finalT", "Single Result: "+result.getDevice().getName());
processResult(result);
/*
scanCallback.onDeviceFound(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());*/
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
Log.d("finalT", "onBatchScanResults: "+results.size()+" results");
/*
for (ScanResult result : results) {
processResult(result);
}*/
}
#Override
public void onScanFailed(int errorCode) {
Log.w("finalT", "LE Scan Failed: "+errorCode);
}
private void processResult(ScanResult result) {
BluetoothDevice device = result.getDevice();
Log.i("finalT", "New LE Device: " + device.getName() + " # " + result.getRssi());
scanCallback.onDeviceFound(result.getDevice(),
result.getRssi(), result.getScanRecord()
.getBytes());
//stopScan();
}
};
ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).setReportDelay(0).build();
scanner.flushPendingScanResults(scanCallbackAfterLollipop);
scanner.startScan(null,settings,scanCallbackAfterLollipop);
return true;
} else {
Log.i("finalT","amgbluetooth: inizia lo startscan() < LL");
scanning = true;
scanCallbackBeforeLollipop = new LeScanCallback() {
#Override
public void onLeScan(BluetoothDevice device, int rssi,
byte[] scanRecord) {
Log.i("finalT","device trovato: "+device.getName());
scanCallback.onDeviceFound(device, rssi, scanRecord);
}
};
return bluetoothAdapter.startLeScan(scanCallbackBeforeLollipop);
}
}
public void stopScan() {
Log.i("debug1","stopScan()");
if(isScanning()) {
Log.i("debug","stopScan() inside if");
//stopTimer.interrupt();
pippo.removeCallbacks(solPippo);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
scanner.stopScan(scanCallbackAfterLollipop);
scanning = false;
} else {
bluetoothAdapter.stopLeScan(scanCallbackBeforeLollipop);
scanning = false;
}
}
}
and in the unlock() I call connect function.
P.S.: the device's name that I want to connect to(nexus 6) is in the macaddress variable.
I have issues with android and BLE, any time i make a scan my app crash and i don't know the reason. I use startLeScan() can this be the reason?
Here is a sample of my code.
here is the place where I initialize for api 18
//API 18
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Sensortag sensortag = new Sensortag(device, SensortagScanner.this,
mSensortagScannerCallback);
synchronized (this) {
for (Sensortag other : mDiscoveredDevices) {
if (sensortag.getName().equals(other.getName())) {
Log.i("SensortagScanner",
"Discovered duplicate device: "
+ other.getName());
return;
}
}
}
mDiscoveredDevices.add(sensortag);
Log.i("SensortagScanner",
"Discovered a device named " + device.getName() + ".");
mCallback.onSensorDiscovered(sensortag);
}
};
here is where i initialize ScanCall and what seems to be wrong looking the error java nulle exception
//API 21
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void initScanCallback() {
if (scanCallback != null)
return;
this.scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
// Do whatever you want
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
Log.d(TAG, "Batch scan results: ");
for (ScanResult result : results) {
Log.d(TAG, "Batch scan result: " + result.toString());
// Do whatever you want
}
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
// scanListener.onScanFinished();
Log.d(TAG, "Scan failed");
}
};
}
here is where i start the scan
#Override
public void startScan(SensorScannerCallback callback) {
mCallback = callback;
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
callback.onScannerUnavailable(this);
return;
}
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
stopScan();
}
}, SCAN_PERIOD);
Log.i("SensortagScanner", "Starting scan...");
mScanning = true;
// ////////////POUR API 21//////////////
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
}
// /////////POUR API <18////////////////
else {
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
try using the method for Android 5 like in the snippet below. It might help.
If it does not, please show more of your code and the error you have when the crash happens.
First, you need a callback, so initialize it correctly depending on the android version.
private void initScanCallback(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
initCallbackLollipop();
}else{
initScanCallbackSupport();
}
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void initCallbackLollipop(){
if(scanCallback != null) return;
this.scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
//Do whatever you want
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
Log.d(TAG, "Batch scan results: ");
for (ScanResult result: results){
Log.d(TAG, "Batch scan result: " + result.toString());
//Do whatever you want
}
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.d(TAG, "Scan failed");
}
};
}
private void initScanCallbackSupport(){
if(callback != null) return;
this.callback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {
String address = device.toString();
String name = device.getName();
// parse uuids according to another stackoverflow post
//List<UUID> uuids = parseUuids(scanRecord);
// TODO Compare detected UUIDs with the uuidFilter
//for(UUID discUUID : uuids)
// for(UUID uuid : BLEScanService.this.uuidFilter)
// if(discUUID.equals(uuid))
BLEScanService.this.scanListener.onDeviceScanned(address, name, uuids, rssi);
}
};
}
Then you can start the scan according to the android version:
public void startScanWithServices(List<String> uuidFilters){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scanLollipop(uuidFilters);
}else{
scanSupport(uuidFilters);
}
// Store filters for later filtering
int size = uuidFilters.size();
this.uuidFilter = new ArrayList<UUID>();
for(int i = 0; i<size; i++){
this.uuidFilter.add(UUID.fromString(uuidFilters.get(i)));
}
if(BuildConfig.DEBUG) Log.d(TAG, "BLE Scan started");
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void scanLollipop(List<String> uuidFilters){
if(scanCallback == null)
initCallbackLollipop();
List<ScanFilter> filters = new ArrayList<ScanFilter>();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // or BALANCED previously
.setReportDelay(0)
.build();
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, scanCallback);
//bluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
}
private void scanSupport(List<String> uuidFilters){
if(callback == null)
initScanCallbackSupport();
//start scan
//boolean success = bluetoothAdapter.startLeScan(uuids, callback);
boolean success = bluetoothAdapter.startLeScan(callback);
//check scan success
if(!success) {
if(BuildConfig.DEBUG) Log.d(TAG, "BLE Scan failed");
scanListener.onScanFinished();
}
}
And then you can stop the scan like this:
public void stopScan(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Stop scan and flush pending scan
bluetoothAdapter.getBluetoothLeScanner().flushPendingScanResults(scanCallback);
bluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
}else{
bluetoothAdapter.stopLeScan(callback);
}
if(BuildConfig.DEBUG) Log.d(TAG, "BLE Scan stopted");
}
Check your manifest file. You should have these permissions
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>