Android can't find any BLE devices

杀马特。学长 韩版系。学妹 提交于 2019-12-08 02:07:46

问题


Here's he problem. I've developed an app for iOS to control an BLE LED device (and a few other things). Everything works fine and smooth. Now I wanted develop the same app for android and I already fail at the scanning of BLE devices. I have tried a few tutorials and sample codes but whatever I do I can't find any devices. I work on a Moto G4 Play. The bluetooth works and I can pair devices in the settings but it won't work with any sample code/tutorial I've tried. For example this one: https://github.com/kaviles/BLE_Tutorials

I build this app as it is and it can't find anything.

So I downloaded a BLE Scanner from the Playstore and that works fine to and finds all devices.

I know it's hard to say without any sample code but I've tried so many and I'm not sure if I miss something completely basic.


回答1:


As discussed in the comments, you have to set up the permissions accordingly if your targetSdk is 23+ or other. The location services must be on.

Manifest permissions for API 23+:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>

To check bluetooth permissions:

    public boolean hasBlePermissions() {
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
            return false;
        } else {
            return true;
        }
    }

To request runtime permissions with :

public void requestBlePermissions(final Activity activity, int requestCode) {
    ActivityCompat.requestPermissions(activity,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
            requestCode);
}

Then to check the grant results from OnRequestPermissionResult:

public boolean checkGrantResults(String[] permissions, int[] grantResults) {
    int granted = 0;

    if (grantResults.length > 0) {
        for(int i = 0; i < permissions.length ; i++) {
            String permission = permissions[i];
            if (permission.equals(Manifest.permission.ACCESS_FINE_LOCATION) ||
                    permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    granted++;
                }
            }
        }
    } else { // if cancelled
        return false;
    }

    return granted == 2;
}

Check location services:

public boolean areLocationServicesEnabled(Context context) {
    LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    try {
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}



回答2:


Thanks for the good explanation. Now I feel quite dumb cause I really don't know how to get this working.

Here's my manifest:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

And here my activity:

public class LightActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private final static int REQUEST_ENABLE_BT = 1;

// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_light);

    if(hasBlePermissions() && areLocationServicesEnabled(this)) {
        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, "Bluetooth low energy is not supported", Toast.LENGTH_SHORT).show();
            finish();
        }

        // Ensures Bluetooth is available on the device and it is enabled. If not,
        // displays a dialog requesting user permission to enable Bluetooth.
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        } else {
            scanLeDevice(true);
        }
    }
}

public boolean hasBlePermissions() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        return true;
    } else {
        return false;
    }
}

public void requestBlePermissions(final Activity activity, int requestCode) {
    ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, requestCode);
}

public boolean checkGrantResults(String[] permissions, int[] grantResults) {
    int granted = 0;

    if (grantResults.length > 0) {
        for(int i = 0; i < permissions.length ; i++) {
            String permission = permissions[i];
            if (permission.equals(Manifest.permission.ACCESS_FINE_LOCATION) || permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    granted++;
                }
            }
        }
    } else { // if cancelled
        return false;
    }

    return granted == 2;
}

public boolean areLocationServicesEnabled(Context context) {
    LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    try {
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

private void scanLeDevice(final boolean enable) {
    if (enable) {


        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}

// Device scan callback.
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("NEW DEVICE", device.getName());
            }
        });
    }
};

}

I just recognized that hasBlePermissions() always returns false even so the permissions in the manifest are set correctly.

UPDATE: Got it working. Once you understand it it's not that hard. First grant the permissions then scan for the device. Here's my updated code in the onCreate method:

int permissionCheck = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);

if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
    if(areLocationServicesEnabled(this)) {
        mHandler = new Handler();

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
            finish();
        }

        final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        scanLeDevice(true);
    }
}



回答3:


Have you tried with android BLE sample code from developer site.

https://developer.android.com/samples/BluetoothLeGatt/index.html

Please make sure about UUID and do needful changes to communicate with android application in this sample code if required.




回答4:


I am using the Cordova plugin cordova-plugin-ble-central, which works well with Android. The Plugin requires the following permissions:

ACCESS_COARSE_LOCATION

BLUETOOTH

BLUETOOTH_ADMIN

Hope this helps,




回答5:


For Xamarin, API>=24 I figured out how to make it work, it might not be intuitive that you need COARSE_LOCATION permission to get the Bluetooth to work. Go to the project on Xamarin > right click > Options > Check the boxes for Bluetooth, and location permissions > OK --> rebuild on device




回答6:


I am also very new to app development, but I managed to adapt the BLE GATT example for my Android 8 device. I hope it works for yours as well:

https://github.com/schollp/BluetoothLEGatt-Android8




回答7:


If you build your project with https://github.com/kaviles/BLE_Tutorials just add this line after you get Adapter in MainActivity:

    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001);


来源:https://stackoverflow.com/questions/42250866/android-cant-find-any-ble-devices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!