0

I´m working on an app for android 5.0 and upper, and I need to show all the available bluetooth low energy devices on a listview and, after that, when a device is clicked I need its mac adress to be saved and to connect to it. The problem is that it doesn´t even show the available devices. After lots of tries i finally get this code:

package com.sma.javier.sma_q.BluetoothLE;

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.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.os.Bundle;
import android.os.Handler;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.sma.javier.sma_q.CustomArrayAdapter;
import com.sma.javier.sma_q.R;

import java.util.ArrayList;
import java.util.List;

public class Connect extends AppCompatActivity {

    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 ArrayList<String> DevicesList;
    private BluetoothGatt mGatt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.bt_connect);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        CollapsingToolbarLayout collapser =
                (CollapsingToolbarLayout) findViewById(R.id.collapser);

        ArrayList<String> DevicesList = new ArrayList<String>();
        ArrayAdapter<String> itemsAdapter =
                new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, DevicesList);

        View rowView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.content_bt_connect, null);
        ListView listView = (ListView) rowView.findViewById(R.id.btDevicesListView);
        listView.setAdapter(itemsAdapter);

        mHandler    =   new Handler();

        /*  Check   to  make    sure    BLE is  supported   */
        if  (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
        {
            Toast.makeText(this,    "BLE    Not Supported",
                    Toast.LENGTH_SHORT).show();
            finish();
        }
        /*  Get a   Bluetooth   Adapter Object  */
        final   BluetoothManager    bluetoothManager    =
                (BluetoothManager)  getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter   =   bluetoothManager.getAdapter();
    }

    @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() {
                    mLEScanner.stopScan(mScanCallback);
                }
            },  SCAN_PERIOD);
            mLEScanner.startScan(filters,   settings,   mScanCallback);
        }
        else {
            mLEScanner.stopScan(mScanCallback);
        }
    }


    private ScanCallback mScanCallback   =   new ScanCallback() {
        @Override
        public void onScanResult(int callbackType,ScanResult result) {
            /*  Connect to  device  found   */
            Log.i("callbackType", String.valueOf(callbackType));
            BluetoothDevice btDevice    =   result.getDevice();
            DevicesList.add(String.valueOf(btDevice));
            connectToDevice(btDevice);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            /*  Process a   batch   scan    results */
            for (ScanResult sr  :   results) {
                Log.i("Scan Item:   ",  sr.toString());
            }
        }
    };


    public void connectToDevice(BluetoothDevice device) {
        if  (mGatt == null){
            mGatt = device.connectGatt(this, false, mainGattCallback);
            scanLeDevice(false);//  will    stop    after   first   device  detection
        }
    }

    private final BluetoothGattCallback mainGattCallback = new BluetoothGattCallback() {
        @Override
        public  void onConnectionStateChange(BluetoothGatt   gatt,   int status, int newState) {
            switch  (newState) {
                case    BluetoothProfile.STATE_CONNECTED:
                    Log.i("mainGattCallback",   "CONNECTED");
                    gatt.discoverServices();
                    break;
                case    BluetoothProfile.STATE_DISCONNECTED:
                    Log.e("mainGattCallback",   "DISCONNECTED");
                    break;
                default:
                    Log.e("mainGattCallback",   "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());
        }
    };

}

That actually just should show the first discovered device, connect to it and get it characteristics. Looking and the log with logcat, i can see that it connects and reads the characteristics, but nothing is displayed on the listview. My layouts are: bt_content.xml for the toolbar

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- App Bar -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!-- Collapser -->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapser"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/image_paralax"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="fitEnd"
                app:layout_collapseMode="parallax"
                android:src="@drawable/icon"/>

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@android:color/transparent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/CustomActionBar" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

And content_bt_connect.xml for the listview:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.sma.javier.sma_q.BluetoothLE.Connect"
    tools:showIn="@layout/bt_connect">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btDevicesListView" />
</RelativeLayout>

But as I have said, it does not work, can somebody help me?? Thanks a lot!!

Javierd98
  • 708
  • 9
  • 27

1 Answers1

0

There is a problem with your approach. In your Connect activity, you inflate content_bt_connect.xml but you never add it to the activity's layout. So you never actually see your listview and any items it has. Rather than inflating the content_bt_connect.xml separately in onCreate(), why not just use it in your activity's layout. Your activity xml should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- App Bar -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!-- Collapser -->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapser"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/image_paralax"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="fitEnd"
                app:layout_collapseMode="parallax"
                android:src="@mipmap/ic_launcher"/>

            <!-- Toolbar -->
            <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@android:color/transparent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

        <ListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btDevicesListView" />

</android.support.design.widget.CoordinatorLayout>

Your onCreate():

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    CollapsingToolbarLayout collapser = (CollapsingToolbarLayout) findViewById(R.id.collapser);

    ArrayList<String> DevicesList = new ArrayList<String>();
    ArrayAdapter<String> itemsAdapter =
            new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, DevicesList);

    ListView listView = (ListView) findViewById(R.id.btDevicesListView);
    listView.setAdapter(itemsAdapter);

    mHandler    =   new Handler();

    /*  Check   to  make    sure    BLE is  supported   */
    if  (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
    {
        Toast.makeText(this, "BLE    Not Supported",
                Toast.LENGTH_SHORT).show();
        finish();
    }
    /*  Get a   Bluetooth   Adapter Object  */
    final BluetoothManager bluetoothManager    =
            (BluetoothManager)  getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter   =   bluetoothManager.getAdapter();
}
androholic
  • 3,633
  • 3
  • 22
  • 23
  • So, I have tried this but still nothing showed on the listview Any other idea?? – Javierd98 Jan 30 '16 at 14:02
  • After you add your device to your DeviceList, are you making sure that you are recreating the adapter with the List and setting it again or using an adapter notifydatasetchanged event? If you don't the list will not refresh with the device you just found. – Zomb Feb 01 '16 at 16:29
  • Also, for Android Marshmallow, make sure you have given location permission from your app and enabled location from settings. Without these, your app will not find any devices. – androholic Feb 01 '16 at 18:34
  • Yes, I have given the permissions as showed here: http://stackoverflow.com/questions/33043582/bluetooth-low-energy-startscan-on-android-6-0-does-not-find-devices But now it does not show any devices, and it doesnt even looks as if it was searchin (Other apps as nRF Master Control shows the devices). Here you can see a logcat from the two apps http://imgur.com/iOTkD9F,sMrekaB How could I fix it?? Thanks a lot – Javierd98 Feb 09 '16 at 22:30