cordova-plugin-bluetoothle icon indicating copy to clipboard operation
cordova-plugin-bluetoothle copied to clipboard

cant scan any devices

Open mcdowellalex opened this issue 5 years ago • 8 comments
trafficstars

Bluetooth and location services are enabled, and I have successfully initialized it. I am trying to connect to an ESP32, and using an nRF bluetooth app I can see and connect to the ESP32. But when I scan for devices on my app (using Ionic with this plugin) I can't seem to find anything. There is no successful callback from startscan=>scanResult. I get the callback scanStarted, but nothing after that.

Where am I going wrong here?

  startScan() {

    let params = {
      "services": [

      ],
      "allowDuplicates": true,
    }
    // bluetoothle.startscan is an observable object
    this.bluetoothle.startScan(params).subscribe((success) => {
      this.setStatus("startScan: " + JSON.stringify(success));
      if (success.status == "scanResult"){
        this.addDevice(success);
      }
      
    }, (error) => {
      console.log("error: " , JSON.stringify(error));
      this.scanError(JSON.stringify(error));
    })

  }

mcdowellalex avatar Mar 27 '20 19:03 mcdowellalex

Here's the rest of the code for reference:

import { Component, NgZone } from '@angular/core';
import { Platform, ToastController } from '@ionic/angular';
import { BluetoothLE } from '@ionic-native/bluetooth-le/ngx';


@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})

export class HomePage {

  constructor(
    public bluetoothle: BluetoothLE, 
    public platform: Platform,
    private ngZone: NgZone,
    public toastController: ToastController) {
      this.platform.ready().then((readySource) => { 

        console.log('Platform ready from', readySource);
  
        this.bluetoothle.initialize().subscribe(ble => {
          console.log('ble', ble.status) // logs 'enabled'
        });
        // this.bluetoothle.enable()  dont think i need this
      });
     }


  statusMessage = "nothing"


  adapterInfo() {
    this.bluetoothle.getAdapterInfo().then((success) => {
      console.log("adapterInfo: " , JSON.stringify(success));
      this.setStatus(success.name);
    })
  }

  // takes in a json object from start scan where the successful status == "scanResult"
  // obejct should look like this:
  // {
  //   "status": "scanResult",
  //   "advertisement": "awArG05L", //Android
  //   "advertisement": { //iOS
  //     "serviceUuids": [
  //       "180D"
  //     ],
  //     "manufacturerData": "awAvFFZY",
  //     "txPowerLevel": 0,
  //     "overflowServiceUuids": [
  //     ],
  //     "isConnectable": true,
  //     "solicitedServiceUuids": [
  //     ],
  //     "serviceData": {
  //     },
  //     "localName": "Polar H7 3B321015"
  //   },
  //   "rssi": -58,
  //   "name": "Polar H7 3B321015",
  //   "address": "ECC037FD-72AE-AFC5-9213-CA785B3B5C63"
  // }
  addDevice(deviceJSON){
    console.log(JSON.stringify(deviceJSON))
  }

  startScan() {

    let params = {
      "services": [

      ],
      "allowDuplicates": true,
    }
    // bluetoothle.startscan is an observable object
    this.bluetoothle.startScan(params).subscribe((success) => {
      this.setStatus("startScan: " + JSON.stringify(success));
      if (success.status == "scanResult"){
        this.addDevice(success);
      }
      
    }, (error) => {
      console.log("error: " , JSON.stringify(error));
      this.scanError(JSON.stringify(error));
    })

  }

  stopScan() {
    this.bluetoothle.stopScan().then((resp) => {
      console.log("stopScan: " , resp);
      this.setStatus(resp.status);
    })
  }

  retrieveConnected() {
    let params = {
      "services": [

      ]
    }

    this.bluetoothle.retrieveConnected(params).then((resp) => {
      console.log("retrieveConnected: " + resp);
      this.setStatus("retrieveConnected");
    })
  }

  // If location permission is denied, you'll end up here
  async scanError(error: string) {
    this.setStatus('Error ' + error);
    const toast = await this.toastController.create({
      message: 'Error scanning for Bluetooth low energy devices',
      position: 'middle',
      duration: 5000
    });
    toast.present();
  }

  setStatus(message: string) {
    console.log("message: " , message);
    this.ngZone.run(() => {
      this.statusMessage = message;
    });
  }
} //end of HomePage class

mcdowellalex avatar Mar 27 '20 19:03 mcdowellalex

Is this on Android or iOS? Which version?

It could be related to #579. Did you try closing the other app and restarting all related devices?

randdusing avatar Apr 04 '20 16:04 randdusing

I'm running android version 10 on a pixel 3a. I had all apps closed when running it. Looking into the android studios catlog, oddly I could see the name of the device I'm trying to connect to, despite not being able to actually connect to with startscan. I added the uses-permission for both fine/course location to the manifest. For hasPermission/requestPermission, how would I target fine location rather than course location?

mcdowellalex avatar Apr 09 '20 01:04 mcdowellalex

Added an update on #579. I don't own any Android devices anymore, so it's much harder to develop. I believe the following needs to be done:

  • Add FINE_LOCATION to plugin.xml
  • Add BACKGROUND_LOCATION to plugin.xml
  • Update hasPermission / requestPermission to use COARSE or FINE depending on version
  • Possibly add new method for requesting background permission, which is only necessary on 10. I wouldn't add this to the original requestPermission since everyone may not need it

randdusing avatar Apr 10 '20 12:04 randdusing

I also have similar problems. Problem: Common initialize, startScan or getAdapterInfo callbacks are not launching (also error ones). Device: Samsung Galaxy S10+ (Android 10) I tried adding/editing the plugin as you recommended but application just won't launch the window to accept permissions (I cleaned cache, uninstalled, installed again). I even tried to allow these permissions manually but application is not launching any callbacks on initialize .then(initializeSuccess, handleError); . Also as I mentioned before, other functionalities such as startScan or getAdapterInfo are not triggering any callback either.

dvelaren avatar Apr 10 '20 18:04 dvelaren

Hi, I had the same issue, the API stated: {"status": "scanStarted"} but did not get any results.

I performed a factory reset and allowed every permission during the phone setup (I recall something about using Bluetooth for location, which I obviously allowed).

I also added which I was not using before the factory reset.

And now it works.. So I would assume it is related to permissions. Although I tried many combinations before the factory reset. This is what I am using in 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-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

taherrera avatar May 09 '20 03:05 taherrera

Manually setting the location permission to on for whatever application the plugin is used in did work. However, this should be a popup for the first time when starting/using this application/bluetooth. Is this something that someone can fix? Can this be set for the plugin or must it be done in cordova?

espenrs avatar Jun 18 '20 13:06 espenrs

Permissions can be requested via: https://github.com/randdusing/cordova-plugin-bluetoothle#requestpermission

randdusing avatar Jun 20 '20 13:06 randdusing