0

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)
sjain
  • 23,126
  • 28
  • 107
  • 185
  • See the code in question. I mentioned the line number there also. It is `new BluetoothAdapter.LeScanCallback() { //This is line 179 causing error...` – sjain Apr 22 '14 at 15:01
  • Perhaps a proguard configuration problem (if you are using a release build processed through that)? Or running on a device which does not have the bluetooth APIs? – Chris Stratton Apr 22 '14 at 15:53
  • I am not using proguard. Just downloaded the source code project from developer site and ran it from eclipse with this exception. My device is `Sony Xperia J` which is having bluetooth feature. – sjain Apr 23 '14 at 06:31
  • The Xperia J specification Bluetooth v2.1 + EDR implies it does not have BLE. – Chris Stratton Apr 23 '14 at 13:56
  • So `bluetooth` feature itself is different thing then `BLE feature` in devices to have ? – sjain Apr 23 '14 at 13:58

1 Answers1

1

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;
  }
itsben
  • 1,017
  • 1
  • 6
  • 11
  • thanks. So I have a blackbox device that is BLE capable which I am using as a sensor to note the speed of the vehicle. That sensor will talk to my android phone to send data. So do my android phone should be BLE capable or classic bluetooth capability will be fine to send and receive data to and from sensor ? – sjain Apr 23 '14 at 14:50
  • It depends on the sensor. Some of them are both Bluetooth Classic and BLE capable. A good way to test it is open your settings on Android device, go to Bluetooth and start a scan. If your sensor doesn't show up then it's BLE only. So did you run the bleCheck() method on your device? – itsben Apr 23 '14 at 15:04
  • Yes, it is returning false. So the sensors which are BLE compatible will never show up on my device ? I can't even do testing of my code with my device as it is not BLE. I have to buy a BLE compatible android phone ? – sjain Apr 23 '14 at 15:18
  • Correct. The Google Nexus 7 (2013) is a nice choice. Samsung devices are nice but I would only get one that comes with Android 4.3 stock. The devices that run Android 4.2 use the Samsung Bluetooth SDK. Can you accept my answer please? – itsben Apr 23 '14 at 17:34
  • +1. May need your help in future development using BLE. Will now need to change my code for BLE discovery/scan as by insufficient knowledge in this area, I made it for Classic Bluetooth discovery/scan which is a different thing and of no use. Thanks. – sjain Apr 24 '14 at 07:14
  • Sure thing. Drop me a line. I have code for both Classic and BLE. – itsben Apr 24 '14 at 11:57