Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

ios - How to run iPhone as a beacon in background in both xcode(swift) and phonegap

I managed to create an app which turns the phone into a beacon emitter.

It works fine on xcode (Swift) and phonegap .

The next step for me is making it work in the background as a beacon (I'm developing for iOS 10).

I found similar questions to this online but all of them were out of date ie old ios , objective-C and outdate plug-ins

would really appreciate it if someone can provide me with a working example or guide me on what to change in my code for both an xcode s(wift) and phonegap

Xcode (Swift 3)

import UIKit
import CoreLocation
import CoreBluetooth

class ViewController: UIViewController,CLLocationManagerDelegate,CBPeripheralManagerDelegate,UITextFieldDelegate{

    var locationManager = CLLocationManager()
    var startLocation: CLLocation!
    var localBeacon: CLBeaconRegion!
    var beaconPeripheralData: NSDictionary!
    var peripheralManager: CBPeripheralManager!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        locationManager.delegate = self

        locationManager.requestAlwaysAuthorization()

        bleSwitch.addTarget(self, action: #selector(ViewController.bleSwitchUpdated(_:)), for: UIControlEvents.valueChanged)

        major.delegate=self
        minor.delegate=self
        txPower.delegate=self

    }

    @IBOutlet weak var minor: UITextField!
    @IBOutlet weak var major: UITextField!
    @IBOutlet weak var txPower: UITextField!
    @IBOutlet weak var bleSwitch: UISwitch!
    @IBOutlet weak var bleView: UIView!
    @IBAction func bleSwitchUpdated(_ sender: UISwitch) {
        if bleSwitch.isOn {
            initLocalBeacon()
            bleView.isHidden = false;
        //bleSwitch.setOn(true, animated: false)
        }
        else {
        stopLocalBeacon()
            bleView.isHidden = true;
        }
    }

    func initLocalBeacon() {
        if localBeacon != nil {
            stopLocalBeacon()
        }

        let localBeaconUUID = "5A4BCFCE-174E-4BAC-A814-092E77F6B7E5"
        let localBeaconMajor: CLBeaconMajorValue = UInt16(major.text!)!
        let localBeaconMinor: CLBeaconMinorValue = UInt16(minor.text!)!

        let uuid = UUID(uuidString: localBeaconUUID)!
        localBeacon = CLBeaconRegion(proximityUUID: uuid, major: localBeaconMajor, minor: localBeaconMinor, identifier: "Your private identifer here")

        beaconPeripheralData = localBeacon.peripheralData(withMeasuredPower: -59)
        peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
    }

    func stopLocalBeacon() {
        peripheralManager.stopAdvertising()
        peripheralManager = nil
        beaconPeripheralData = nil
        localBeacon = nil
    }

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        if peripheral.state == .poweredOn {
            peripheralManager.startAdvertising(beaconPeripheralData as! [String: AnyObject]!)
        } else if peripheral.state == .poweredOff {
            peripheralManager.stopAdvertising()
        }
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
        if bleSwitch.isOn == true{
        stopLocalBeacon()
            initLocalBeacon()
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

Phonegap

    var app = (function()
{

           // Application object.
    var app = {};

    // Background flag.
    var mAppInBackground = false;

        app.initialize = function()
    {
        document.addEventListener('deviceready', onDeviceReady, false);
        document.addEventListener('pause', onAppToBackground, false);
        document.addEventListener('resume', onAppToForeground, false);
    };

    function onDeviceReady()
    {
        startMonitoringAndRanging();
        startNearestBeaconDisplayTimer();
        displayRegionEvents();

    }

    function onAppToBackground()
    {
        mAppInBackground = true;
        stopNearestBeaconDisplayTimer();
    }

    function onAppToForeground()
    {
        mAppInBackground = false;
        startNearestBeaconDisplayTimer();
        displayRegionEvents();
    }


    function startMonitoringAndRanging()
    {

        // Request permission from user to access location info.
        cordova.plugins.locationManager.requestAlwaysAuthorization();

           BleconOn();

    }


           function BleconOn(){
           var uuid = '00000000-0000-0000-0000-000000000000';
           var identifier = 'advertisedBeacon';
           var minor = 2000;
           var major = 5;
           var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid, major, minor);

           var delegate = new cordova.plugins.locationManager.Delegate();


           delegate.peripheralManagerDidStartAdvertising = function(pluginResult) {
           console.log('peripheralManagerDidStartAdvertising: '+ JSON.stringify(pluginResult.region));
           };
           // Event when bluetooth transmission state changes
           // If 'state' is not set to BluetoothManagerStatePoweredOn when advertising cannot start
           delegate.peripheralManagerDidUpdateState = function(pluginResult) {
           console.log('peripheralManagerDidUpdateState: '+ pluginResult.state);
           };

           cordova.plugins.locationManager.setDelegate(delegate);

           // Verify the platform supports transmitting as a beacon
           cordova.plugins.locationManager.isAdvertisingAvailable()
           .then(function(isSupported){

                 if (isSupported) {
                 cordova.plugins.locationManager.startAdvertising(beaconRegion)
                 .fail(conole.error)
                 .done();
                 } else {
                 console.log("Advertising not supported");
                 }
                 })
           .fail(function(e) { console.error(e); })
           .done();
           }

           function BleconOff(){

           cordova.plugins.locationManager.stopAdvertising()
           .fail(console.error)
           .done();
           }



    return app;

})();

app.initialize();

for both codes , the location updates and background fetch are checked in the background capabilities for the target. Also , Privacy - Location Always Usage Description is added on both playlists

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Unfortunately, Apple blocks the ability to transmit as a beacon in the background on iOS. All CoreBluetooth standard advertisements are actually blocked, because advertising slots are a limited resource and multiple apps in the background would exhaust this resource quickly.

Apple does have a proprietary backup system for advertising Bluetooth services in the background that uses a special overflow area to include the service identifiers. But while this scheme works for advertising Bluetooth services in the background, it does not work for advertising beacons, because it breaks the format.

Bottom line: background beacon advertising on iOS just does not work. Sorry.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...