Unable to write to Arduino from Android using BLE - android

I'm having a problem. I am attempting to write a value to my Arduino from my Android smartphone over BLE. My board is a Genuino 101, so I am using CurieBLE. I am able to access the correct service and characteristic, but I always get a false value returned from writeCharacteristic. The onCharacteristicWrite function is also not being called.
Here is the code for my Bluetooth class:
public class BluetoothActivity extends AppCompatActivity{
private BluetoothAdapter btAdapt = BluetoothAdapter.getDefaultAdapter();
private boolean mScan;
private BluetoothGatt mGatt;
private Handler handler = new Handler();
private static final long SCAN_TIME = 10000;
private static final String DEVICE_ADDRESS = "98:4F:EE:0F:CB:69";
private static final String LIGHT_SERVICE = "19B10000-E8F2-537E-4F6C-D104768A1214";
private Context context = this;
private BluetoothGattCharacteristic sendVal;
/**
* Function to scan device
* #param enable: Switch to begin scanning
*/
public void ScanDevice(final boolean enable){
if(enable){
handler.postDelayed(new Runnable() {
#Override
public void run() {
mScan = false;
btAdapt.stopLeScan(mCallback);
}
}, SCAN_TIME);
mScan = true;
btAdapt.startLeScan(mCallback);
}else{
mScan = false;
btAdapt.stopLeScan(mCallback);
}
}
/**
* Callback to execute upon finding device.
*/
private BluetoothAdapter.LeScanCallback mCallback = new BluetoothAdapter.LeScanCallback() {
#Override
//!Function to connect to device
public void onLeScan(final BluetoothDevice device, int i, byte[] bytes) {
String address = device.getAddress();
if(address.equals(DEVICE_ADDRESS)) {
mGatt = device.connectGatt(context, false, bCallback);
Log.i("BTConnect", "Found it!");
}
else{
Log.i("BTConnect", "Wrong device!");
}
}
};
/**
* Callback to find services of device.
*/
private final BluetoothGattCallback bCallback = new BluetoothGattCallback() {
//!Function to discover services
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
gatt.discoverServices();
}
//!Function to deal with discovered services
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
mGatt = gatt;
List<BluetoothGattService> bluetoothGattServiceList= mGatt.getServices();
BluetoothGattService LightUp = bluetoothGattServiceList.get(findService(bluetoothGattServiceList));
List<BluetoothGattCharacteristic> bluetoothGattCharacteristicList = LightUp.getCharacteristics();
sendVal = bluetoothGattCharacteristicList.get(findCharacteristic(bluetoothGattCharacteristicList));
}
//!Function to deal with characteristic writes
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS){
Log.i("BTWrite","Write to Characteristic Success!");
}else{
Log.i("BTWrite","Blast!Foiled!");
}
}
};
//!Function to find the right service
private int findService(List<BluetoothGattService> list){
int index = 0;
for(int i = 0; i<list.size(); i++){
if(list.get(i).getUuid().equals(LIGHT_SERVICE)){
index = i;break;}
}
return index;
}
//!Function to find the right characteristic
private int findCharacteristic(List<BluetoothGattCharacteristic> list){
int index = 0;
for(int i = 0; i<list.size(); i++){
if(list.get(i).getUuid().equals(LIGHT_SERVICE)){
index = i;break;}
}
return index;
}
//!Function to actually write to Arduino
public boolean WriteVal(){
if(sendVal==null){
Log.i("BTWrite", "Disconnected!");
return false;
}
byte[] value = new byte[1];
value[0] = (byte) (Math.random() * 126);
sendVal.setValue(value);
boolean ans = mGatt.writeCharacteristic(sendVal);
return ans;
}
}
And here is the main class which contains the UI:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter btAdapt = BluetoothAdapter.getDefaultAdapter();
BluetoothActivity btActivity = new BluetoothActivity();
/**
* Main function for opening screen.
* #param savedInstanceState: Instance for creation
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//!Open the layout
if(btAdapt.isEnabled()){
Intent enableBt = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBt, REQUEST_ENABLE_BT);
}
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);//!Set listener to button
}
#Override
public void onClick(View v){
switch(v.getId()) {
case R.id.button1:
btActivity.ScanDevice(true);break;//!Scan for shisha
case R.id.button2:
btActivity.WriteVal();break;//!Write to shisha
}
}
}
I appreciate all your help. Thank you in advance.

Your infinite do-while loop doesn't look so good (why is it there?). Since having that means you won't return from the onServicesDiscovered method, and therefore you block the onCharacteristicWrite callback from running (it gets enqueued). Also note that in Android you may only have one outstanding GATT operation per BluetoothGatt object (you must wait until the corresponding callback arrives before you can issue another operation). That is the reason for your writeCharacteristic calls return false.

Related

Why MainActivity is declared static inside other Class?

I followed a tutorial on Bluetooth Low Energy, and I have started to add my own menus, etc.
The question I have is, why would MainActivity be static and put inside another class.
The full tutorial is available on Github: https://github.com/kaviles/BLE_Tutorials
Below is the Scanner_BTLE class that contains static MainActivity.
public class Scanner_BTLE {
private MainActivity ma;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private long scanPeriod;
private int signalStrength;
private UUID[] uuids;
// ToDO add Runtime Permissions to activate it momentarily once user asks for scanning
// ToDo this is currently done in App permitions while in dedug mode, add the software in the code so //permisiions does not have to be done on phone
// ToDo see "https://andela.com/insights/how-to-scan-for-android-bluetooth-low-energy-devices-successfully/"
// ToDO Look at "B- or add Runtime Permissions..... " on how to add it in code
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public Scanner_BTLE(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();
}
public boolean isScanning() {
return mScanning;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void start() {
if (!Utils.checkBluetooth(mBluetoothAdapter)) {
Utils.requestUserBluetooth(ma);
ma.stopScan();
}
else {
scanLeDevice(true);
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void stop() {
scanLeDevice(false);
}
//ToDo Use the Callback to find only the sps UUID of Relay
// 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.
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
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;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int new_rssi = rssi;
if (rssi > signalStrength) {
mHandler.post(new Runnable() {
#Override
public void run() {
ma.addDevice(device, new_rssi);
}
});
}
}
};
public static class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private final static String TAG = MainActivity.class.getSimpleName();
public static final int REQUEST_ENABLE_BT = 1;
public static final int BTLE_SERVICES = 2;
private HashMap<String, BTLE_Device> mBTDevicesHashMap;
private ArrayList<BTLE_Device> mBTDevicesArrayList;
private ListAdapter_BTLE_Devices adapter;
private ListView listView;
private Button btn_Scan;
private BroadcastReceiver_BTState mBTStateUpdateReceiver;
private Scanner_BTLE mBTLeScanner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Utils.toast(getApplicationContext(), "BLE not supported");
finish();
}
mBTStateUpdateReceiver = new BroadcastReceiver_BTState(getApplicationContext());
mBTLeScanner = new Scanner_BTLE(this, 5000, -75);
mBTDevicesHashMap = new HashMap<>();
mBTDevicesArrayList = new ArrayList<>();
adapter = new ListAdapter_BTLE_Devices(this, R.layout.btle_device_list_item, mBTDevicesArrayList);
listView = new ListView(this);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
btn_Scan = (Button) findViewById(R.id.btn_scan);
((ScrollView) findViewById(R.id.scrollView)).addView(listView);
findViewById(R.id.btn_scan).setOnClickListener(this);
}
#Override
protected void onStart() {
super.onStart();
registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
#Override
protected void onResume() {
super.onResume();
// registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
#Override
protected void onPause() {
super.onPause();
// unregisterReceiver(mBTStateUpdateReceiver);
stopScan();
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(mBTStateUpdateReceiver);
stopScan();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
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");
}
}
else if (requestCode == BTLE_SERVICES) {
// Do something
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Context context = view.getContext();
// Utils.toast(context, "List Item clicked");
// do something with the text views and start the next activity.
stopScan();
String name = mBTDevicesArrayList.get(position).getName();
String address = mBTDevicesArrayList.get(position).getAddress();
Intent intent = new Intent(this, Activity_BTLE_Services.class);
intent.putExtra(Activity_BTLE_Services.EXTRA_NAME, name);
intent.putExtra(Activity_BTLE_Services.EXTRA_ADDRESS, address);
startActivityForResult(intent, BTLE_SERVICES);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_scan:
Utils.toast(getApplicationContext(), "Scan Button Pressed");
if (!mBTLeScanner.isScanning()) {
startScan();
}
else {
stopScan();
}
break;
default:
break;
}
}
public void addDevice(BluetoothDevice device, int rssi) {
String address = device.getAddress();
if (!mBTDevicesHashMap.containsKey(address)) {
BTLE_Device btleDevice = new BTLE_Device(device);
btleDevice.setRSSI(rssi);
mBTDevicesHashMap.put(address, btleDevice);
mBTDevicesArrayList.add(btleDevice);
}
else {
mBTDevicesHashMap.get(address).setRSSI(rssi);
}
adapter.notifyDataSetChanged();
}
public void startScan(){
btn_Scan.setText("Scanning...");
mBTDevicesArrayList.clear();
mBTDevicesHashMap.clear();
mBTLeScanner.start();
}
public void stopScan() {
btn_Scan.setText("Scan Again");
mBTLeScanner.stop();
}
}
}

Android Bluetooth Low Energy Not Finding Devices

I am trying to set up a basic Android App that will have Bluetooth LE functionality as per the documentation on the Android Developers site. I successfully can get to the point where I am starting a scan, but it is not finding any of the peripherals I have been using to test. Here is the code as it is:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Bind(R.id.button) Button mButton;
#Bind(R.id.listView) ListView mListView;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning = true;
private Handler mHandler;
private static final long SCAN_PERIOD = 10000;
BluetoothLeScanner mBluetoothAdapterBluetoothLeScanner;
ArrayList<String> bluetoothArray = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mButton.setOnClickListener(this);
Context mContext = getBaseContext();
final BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mBluetoothAdapterBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1900);
}
}
#Override
public void onClick(View view) {
scanLeDevice(mScanning);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
// mHandler.postDelayed(new Runnable() {
// #Override
// public void run() {
// mScanning = false;
// mBluetoothAdapter.stopLeScan(mLeScanCallback);
// }
// }, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
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.d("test" ,device.getName());
}
});
}
};
}
Do you know exactly what the advertising data content is? Maybe it's blocked by the bluetooth stack(bluetooth.default.so) .For example, if the advertising device has not set the "discoverable bit" in AD flag, it will be blocked and you will not receive the report in your callback function.

BLE Device Scan not working in Dialogfragment

Here I have a listview to show the list of scanned ble devices. This is working fine in ListActivity, but I want to do the same scan on DialogFragment on a button click. The working code which I have used in ListActivity is not working in DialogFragment. It is not even showing the Dialogfragment itself when I click on Button to trigger the dialog. so I have added a time with handler for 1500ms. then It shows only the Dialog title but not the list of scanned device. any idea to achieve list of scanned devices in Dialogfragment
public class DeviceScanDialogFragment extends DialogFragment
{
private static final String TAG = "DeviceScan";
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
private BluetoothDevice selectedDevice;
private Logger logger = LoggerFactory.getLogger(this.getClass());
private String calledFrom;
//persist the value about where to start the application
public static boolean isVerified = false, isPinChanged = false, isFingerPrintRegistered = false;
private SharedPreferences sharedPreferences;
private ListView listview;
public DeviceScanDialogFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(getActivity(), R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
getActivity().finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getActivity().getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
// logger.info("Bluetooth adapter is null");
Toast.makeText(getActivity(), R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
getActivity().finish();
return;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.list_dialog_fragment, container);
listview = (ListView) rootview.findViewById(R.id.list);
Toast.makeText(getActivity(), "Executed", Toast.LENGTH_SHORT).show();
// getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().setTitle("Scan List Title");
return rootview;
}
#Override
public void onResume() {
super.onResume();
// 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()) {
// logger.info("Enabling bluetooth");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
listview.postDelayed(new Runnable() {
#Override
public void run() {
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
listview.setAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
},1500);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
getActivity().finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
// save(isVerified, isPinChanged, isFingerPrintRegistered);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
if (mBluetoothAdapter != null) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
if (mBluetoothAdapter.getBondedDevices().size() == 0)
Toast.makeText(getActivity(), "No Device Found", Toast.LENGTH_SHORT).show();
if (getActivity() != null) {
if (isVisible())
dismiss();
}
}
// invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
// logger.info("Scanning without UUIDs");
mBluetoothAdapter.startLeScan(mLeScanCallback);
/*UUID[] uuids = new UUID[1];
Log.e(TAG, "Length of UUID[]= " + uuids.length);
uuids[0] = UUID.fromString(SampleGattAttributes.JACKET_UUID);
logger.info("Scanning with UUIDs");
mBluetoothAdapter.startLeScan(uuids, mLeScanCallback);*/
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
// invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflater;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflater = getActivity().getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if (!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflater.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(position);
final String deviceName = device.getName();
Log.i(TAG, "name:" + deviceName + ", Address :" + device.getAddress());
if (deviceName != null && deviceName.length() > 0) {
viewHolder.deviceName.setText(deviceName);
if (deviceName.contains("Test")) {
selectedDevice = mLeDeviceListAdapter.getDevice(position);
if (selectedDevice != null) {
Intent intent;
intent = new Intent(getActivity(), NavigationDrawerActivity.class);
intent.putExtra("address", selectedDevice.getAddress());
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
}
startActivity(intent);
}
}
} else {
viewHolder.deviceName.setText(R.string.unknown_device);
}
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
}
On Button click I am Calling this method to trigger the Dialogfragment
public void showScanDialog() {
FragmentManager manager = getSupportFragmentManager();
DeviceScanDialogFragment dialog = new DeviceScanDialogFragment();
dialog.show(manager, "devicescan");
}
Everything is working fine when I turned off wifi, because BLE won't stable with wifi and Using BLE in Marshmallow Devices will won't show the Scanned devices which are nearby. so just I have added permissions for location access for Marshmallow supported Devices, Then it worked fine.

Working with Android Bluetooth 4.0

I am developing an App which connects to heart rate sensor and retrives the values. I am using BLE 4.0.
With the help of google developer portal, I was able to build some code, but the app is crashing.
Please help me out. And also I need to sync the data which I have not able to able properly.
Code:
public class PollingTest extends Activity{
public Button btn2;
public static String UUID = "00001101-0000-1000-8000-00805F9B34FB";
public boolean mScanning;
public Handler mHandler;
public LeDeviceListAdapter mLeDeviceListAdapter;
public BluetoothAdapter mBluetoothAdapter;
static final int REQUEST_ENABLE_BT = 1;
public static final long SCAN_PERIOD = 10000; // Stops scanning after 10 seconds.
#Override
protected void onCreate(Bundle savedInstanceStat){
super.onCreate(savedInstanceStat);
setContentView(R.layout.pollingactivity);
btn2 = (Button)findViewById(R.id.pollB);
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
btn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(getApplicationContext(), "Bluetooth Low Energy is not supported on this Device ", Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(getApplicationContext(), "Bluetooth not Supported", Toast.LENGTH_SHORT).show();
finish();
return;
}
else {
if (!mBluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
} else {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
scanLeDevice(true);
}
}
}
});
}
#Override
protected void onResume() {
super.onResume();
// 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()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
//mLeDeviceListAdapter.clear();
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
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() {
//String macAddress;
//macAddress = device.getAddress();
Toast.makeText(getApplicationContext(),device.getAddress(),Toast.LENGTH_LONG).show();
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
/*switch (device.getAddress().toUpperCase()){
case "8C:DE:52:64:8E:D1":
Toast.makeText(getApplicationContext(), "First",Toast.LENGTH_LONG).show();
}*/
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<>();
mInflator = PollingTest.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if(!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}
}
Here I have commented onResume & onPause methods because,if dont,the app is getting crashed.
Log
I think device in LeScan if not able to access/receive bluetooth object for some weird reason or something. Please help me out
Thank You
It's because DeviceScanActivity.this returns 'null' (that pattern is likely not correctly set up), so when you call DeviceScanActivity.this.getLayoutInflater(), you get a NullPointerException, because you're trying to call getLayoutInflater() on something that does not exist.

Bluetooth Low Energy device scanning Failed with an exception

I am referring to developer docs to scan BLE devices -
http://developer.android.com/guide/topics/connectivity/bluetooth-le.html
In my activity class LookUpActivity, I called a method findBLE() on a button click-
//This will scan BLE devices
public void findBLE()
{
Intent intent = new Intent(LookUpActivity.this, DeviceScanActivity.class);
startActivity(intent);
}
But got the following exception -
Could not find class 'com.testapp.main.DeviceScanActivity$1',
referenced from method com.testapp.main.DeviceScanActivity.<init>
com.testapp.main fatal error : com.testapp.main.DeviceScanActivity$1
java.lang.NoClassDefFoundError: com.testapp.main.DeviceScanActivity$1
at com.testapp.main.DeviceScanActivity.<init>(DeviceScanActivity.java:179)
DeviceScanActivity.java ---
/**
* Activity for scanning and displaying available Bluetooth LE devices.
*/
#SuppressLint("NewApi")
public class DeviceScanActivity extends ListActivity {
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
// 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()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if(!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.mapentries, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.entriestitle);
//viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
/* if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);*/
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() { //This is line 179 causing error...
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
//TextView deviceName;
TextView deviceAddress;
}
}
UPDATE:
In order to be more specific, I downloaded the exact project code for BLE from ---
http://developer.android.com/samples/BluetoothLeGatt/project.html
And again got the same exception even using the code mentioned in the project.
This time the error console--
FATAL EXCEPTION: main
java.lang.NoClassDefFoundError:
com.example.android.bluetoothlegatt
.DeviceScanActivity$1
at com.example.android.bluetoothlegatt.DeviceScanActivity.
<init> (DeviceScanActivity.java:250)
You must perform the full check to see if the device supports Bluetooth Low Energy (BLE). The device could be running Android 4.3 or later but lacks the hardware necessary for BLE. The Nexus 7 (2012) is an example of such device. Here's the code:
private boolean bleCheck() {
boolean result = false;
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager != null) {
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter != null) {
if (mBluetoothAdapter.isEnabled()) {
result = true;
}
}
}
}
return result;
}

Categories

Resources