简体   繁体   中英

Cordova plugin - Callback only executed once

I'm trying to update the BluetoothSerial cordova plugin with the necessary code to run with Windows Universal. Unfortunately, I'm unable to figure out a work-around for the following problem.

Let say I want to connect my smartphone through bluetooth to another bluetooth device using Serial Port. Obviusly, the first thing to do is to call the connect method of the plugin, which is going to initialize a writer and a reader and will also start the asyncronous reading loop, provided by the function receiveStringLoop . The other bluetooth device is constantly sending data, so I want to subscribe my phone to that bluetooth device, which means my app will automatically process the incoming data as it arrives. Here is an extremely simplified version of the app code.

ns.connect = function (event) {
    var device = event.target.getAttribute("did");
    bluetoothSerial.connect(device, led.onconnect, led.ondisconnect);
}

ns.onconnect = function() {
    var success = function (data) {
        console.log("Success receiving subscribed data: " + data);
    };

    var failure = function () {
        console.log("Failed to receive...");
    };

    bluetoothSerial.subscribe('\n', success, failure);
}

ns.ondisconnect = function(err) {
    console.log(err);
}

Lets look at the plugin code. Since the code is quite long, let me post the link to it . When the subscribe method is called, the plugin will store the delimiter (which is a character used to separate two different incoming messages) and the success callback. If data is red from the plugin, and subscribe was previusly called, then the plugin will execute the success callback sending back the data.

receiveStringLoop: function(reader) {
        // Read first byte (length of the subsequent message, 255 or less). 
        reader.loadAsync(1).done(function (size) {      
            if (size != 1) {
                bluetoothSerial.disconnect();
                console.log("The underlying socket was closed before we were able to read the whole data. Client disconnected.", "sample", "status");
                return;
            }

            // Read the message. 
            var messageLength = reader.readByte();
            console.log("messageLength: " + messageLength);

            reader.loadAsync(messageLength).done(function(actualMessageLength) {
                if (messageLength != actualMessageLength)
                {
                    // The underlying socket was closed before we were able to read the whole data. 
                    console.log("The underlying socket was closed before we were able to read the whole data.", "sample", "status");
                    return;
                }

                var message = reader.readString(actualMessageLength);                   
                console.log("Message readed: " + message + " - Length: " + message.length);
                buffer = message;

                if (subscribeCallback && typeof(subscribeCallback) !== "undefined") {
                    var tmp = readUntil(delimiter);
                    console.log("Data to send to subscriber: " + tmp);

                    subscribeCallback(tmp);
                }

                WinJS.Promise.timeout().done(function () { return module.exports.receiveStringLoop(reader); });
            }, function (error) {
                console.log("loadAsync -> Failed to read the message, with error: " + error, "sample", "error");
            });
        }, function (error) {
            console.log("Failed to read the message size, with error: " + error, "sample", "error");
        });
    },

The problem is that the subscribeCallback is correctly executed only the first time (when the first message has arrived, it will be printed into the log through the callback). Next, the console logs show that subscribeCallback is indeed called every time a message has arrived, but for some reason it won't print the incoming messages.

Please, I need help to figure out what is going on.

I have finally found the solution, thanks to this blog post .

I write this in the hope it's going to be usefull to somebody else. By default Cordova don't allow to call the success callback more than once. On other platforms (Android, iOS), it is possible to force Cordova by setting to true the property setKeepCallbackAsBool (or KeepCallback) of the PluginResult object. When you develop a plugin for Windows Universal (using javascript), there is no PluginResult object. The workaround is to pass the callback as an additional parameter. Let me post a code to explain.

This is a piece of code without the workaround of the file myPluginFolder/www/myPlugin.js

subscribe: function (delimiter, success, failure) {
    cordova.exec(success, failure, "BluetoothSerial", "subscribe", [delimiter]);
}

And this is the related piece of code of the file myPluginFolder/src/windows/MyPlugin.js

subscribe: function(success, failure, args) {
    delimiter = args[0];
    subscribeCallback = success;
}

In this case the subscribeCallback will be executed only once. Now let me post the workaround code:

This is a piece of code of the file myPluginFolder/www/myPlugin.js

subscribe: function (delimiter, success, failure) {
    cordova.exec(success, failure, "BluetoothSerial", "subscribe", [delimiter, success]);
}

Note how I placed the success callback also into the array arguments. And this is the related piece of code of the file myPluginFolder/src/windows/MyPlugin.js

subscribe: function(success, failure, args) {
    delimiter = args[0];
    subscribeCallback = args[1];
}

With this workaround I can finally call the subscribeCallback as many times as I need.

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