I am working on a hardware device that sends a continuous stream of data through BLE to an Android app. The android application receives this data in the form of GATT notifications, then processes this data and stores it in the database.
The project configuration details are as follows:
- Phone - Moto E 1st Generation
- Android version - Android 5.1 - Lollipop
- iOS - iPhone 4 and 5 tested on iOS 7 and 8
- Equipment - CC2541
- Connection_Interval: 40 ms (installed in the firmware of the hardware).
- Packets sent for the interval between connections: 4 (installed in the firmware of the hardware).
PROBLEM
When data is transferred from a hardware device to a BLE data capture application running on an Android phone, all data packets are not received. It receives only about 35-45 packets, while the expected number of packets is 50.
What is more surprising is that when we used the BLE packet sniffer, there was a perfect match between the data sniffed and displayed on the Android phone (which is incomplete / incorrect data). This makes me think that the hardware behaves differently when connected to an Android phone and does not send all the data.
When we use the same equipment with the iOS BLE data capture application, the data is received correctly.
I am puzzled and don't know about this behavior of BLE data in Android. How can an application on an iOS device correctly record all data, while an application on an Android phone cannot correctly record data?
Has anyone encountered such a packet loss / invalid data issue when using the BLE application on Android? Any inputs are welcome. Thank you so much for your help in advance.
The Android application uses the standard BLE code to connect to the device via BLE. Below is the Android code I am using:
import android.annotation.TargetApi; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; 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.content.pm.PackageManager; import android.nfc.Tag; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.widget.Toast; import java.util.ArrayList; import java.util.List; @TargetApi(21) public class BLETestActivity extends Activity { 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_bletest); 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) { Log.i("innnnn","spinnnn - " + Build.VERSION.SDK_INT); 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) {
source share