简体   繁体   中英

IONIC Capacitor BLE plugin scan not working

I am learning ionic 5 and want to create a simple app which display list of all nearby Bluetooth enabled phones. My problem is that when I use invoke scan of BLE plugin, my callback methods are never invoked. I tested this on attached phone (Samsung 9 ) and also by generating app-debug.apk and install on phone.

Here are the details of my project. I am using Capacitor for native apps.

SDK: 在此处输入图像描述

tab-1.ts

import { Component, NgZone } from '@angular/core';
import { BLE } from '@ionic-native/ble/ngx';
import { AlertController } from '@ionic/angular';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
text = 'hello';
devices: any[] = [];
constructor(private ble: BLE,
            private ngZone: NgZone,
            public alertController: AlertController) { }
 scan() {
  this.text = 'Loading...';
  console.log('going to this.scan.....');
  this.devices = [];
  this.showAlert('starting scan.....');


  this.ble.scan([], 60).subscribe(devices1=>{
    this.showDeviceList(devices1);
    this.text = devices1;
    this.showAlert('scan finished success');
  },error=> this.showAlert('scan fini with error'), 
  ()=>this.showAlert('scan void finish'));
}

async showDeviceList(devices) {
  const alert = await this.alertController.create({
    header: 'Alert',
    subHeader: 'Subtitle',
    message: 'Going to start scan',
    buttons: ['OK']
  });
  await alert.present();
  console.log('devices are ', devices);
  this.ngZone.run(() => {
    this.devices.push(...devices);
    this.text = 'finished';
  });
}

async showAlert(msg){
  const alert = await this.alertController.create({
    header: 'Alert',
    subHeader: 'Subtitle',
    message: msg,
    buttons: ['OK']
  });
  await alert.present();
}
}

ionic info:

在此处输入图像描述

Package.json:

{
  "name": "COVID-TRACKING",
  "version": "0.0.1",
  "author": "Ionic Framework",
  "homepage": "https://ionicframework.com/",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "~8.2.14",
    "@angular/core": "~8.2.14",
    "@angular/forms": "~8.2.14",
    "@angular/platform-browser": "~8.2.14",
    "@angular/platform-browser-dynamic": "~8.2.14",
    "@angular/router": "~8.2.14",
    "@capacitor/android": "^2.0.1",
    "@capacitor/core": "2.0.1",
    "@ionic-native/ble": "^5.23.0",
    "@ionic-native/core": "^5.0.7",
    "@ionic-native/splash-screen": "^5.0.0",
    "@ionic-native/status-bar": "^5.0.0",
    "@ionic/angular": "^5.0.0",
    "cordova-plugin-ble-central": "^1.2.4",
    "core-js": "^2.5.4",
    "rxjs": "~6.5.1",
    "tslib": "^1.9.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.803.20",
    "@angular/cli": "~8.3.23",
    "@angular/compiler": "~8.2.14",
    "@angular/compiler-cli": "~8.2.14",
    "@angular/language-service": "~8.2.14",
    "@capacitor/cli": "2.0.1",
    "@ionic/angular-toolkit": "^2.1.1",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "~8.9.4",
    "codelyzer": "^5.0.0",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.4.3"
  },
  "description": "An Ionic project"
}

Command to install plugin:

npm install cordova-plugin-ble-central
npm install @ionic-native/ble
ionic cap sync

The problem is only with android 10. You need backgound location permission in android 10 to get bluetooth to work. You need to add background location permission to your AndroidManifest.xml and you also need to add the Background Geolocation plugin to your app even if you are not going to use it. In your app.component do something like this

const config: BackgroundGeolocationConfig = {
    desiredAccuracy: 10,
    stationaryRadius: 20,
    distanceFilter: 30,
    debug: true, //  enable this hear sounds for background-geolocation life-cycle.
    stopOnTerminate: false, // enable this to clear background location settings when the app terminates
  };

  this.bgLoc.stop();

After doing the above this will automatically request for background location permission and will allow Bluetooth to work on android 10. Also make sure you add Coarse Location permission to your androidmanifest.xml

Since android api 29, ACCESS_FINE_LOCATION permission is used instead of ACCESS_COARSE_LOCATION. The mantainer of cordova-plugin-ble-central have not accepted a pull request that fix this issue yet.

I did the necessary changes on my fork and it is working fine now on android 10, without tha hack of adding background location to your app..

Maybe you can use it by removing the old:

ionic cordova plugin rm cordova-plugin-ble-central

And adding my fork:

ionic cordova plugin add git+https://github.com/dslima90/cordova-plugin-ble-central.git

tried capacitor and found plentty issues it takes too much time so I decide to switch back to cordova instead of capacitor

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM