evothings / cordova-ble

Bluetooth Low Energy plugin for Cordova
http://www.evothings.com/
Apache License 2.0
242 stars 103 forks source link

On Android 5 (L), app crashes when bluetooth is disabled #103

Closed qpwr closed 8 years ago

qpwr commented 8 years ago

Hey Mikael,

If the app is started, a dialog pops up to tell the user that the app wants to enable bluetooth and asks whether they want to allow it. When you click yes, the same dialog is shown again and when you press yes again, the app crashes. Bluetooth is enabled correctly though and if you start the app again, it will just work because Bluetooth is enabled then.

Can you confirm this issue?

Thanks for all your work.

Marc

ghost commented 8 years ago

@qpwr Hi Marc, I have tested this scenario on an LG G2 with Android 5.0.2, but did not experience the repeated dialog display.

Which device are you using? Would it be possible to get the output from adb logcat when the crash happens? That could provide clues to the problem.

Best, Mikael

qpwr commented 8 years ago

@mikaelkindborg, as far as I can see, this should be the output. I waited for the dialog to appear and then confirmed it. This is what followed (Huawei Honor, but other users with other devices confirming, too). By the way, I now can't reproduce the repeated dialog anymore, but the app still crashes when confirming the "enable bluetooth" request.

UPDATE: I tested on Android 4.4.2 actually, which doesn't show the repeated dialog. I could see the dialog on Android 5 only.

E/bt_gap_api.c( 1375): [GAP] btmtk_paired_dev_cache_init open error 2: No such file or directory
E/RequestPermissionActivity( 7824): Unexpected onActivityResult 5 0
E/AndroidRuntime(16219): FATAL EXCEPTION: main
E/AndroidRuntime(16219): Process: com.trademarc.smartrace, PID: 16219
E/AndroidRuntime(16219): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=0, result=0, data=null} to activity {com.trademarc.smartrace/com.trademarc.smartrace.MainActivity}: java.lang.NullPointerException
E/AndroidRuntime(16219):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3604)
E/AndroidRuntime(16219):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3647)
E/AndroidRuntime(16219):    at android.app.ActivityThread.access$1400(ActivityThread.java:151)
E/AndroidRuntime(16219):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1402)
E/AndroidRuntime(16219):    at android.os.Handler.dispatchMessage(Handler.java:110)
E/AndroidRuntime(16219):    at android.os.Looper.loop(Looper.java:193)
E/AndroidRuntime(16219):    at android.app.ActivityThread.main(ActivityThread.java:5345)
E/AndroidRuntime(16219):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(16219):    at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime(16219):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
E/AndroidRuntime(16219):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
E/AndroidRuntime(16219):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(16219): Caused by: java.lang.NullPointerException
E/AndroidRuntime(16219):    at com.evothings.BLE.onActivityResult(BLE.java:199)
E/AndroidRuntime(16219):    at org.apache.cordova.CordovaInterfaceImpl.onActivityResult(CordovaInterfaceImpl.java:151)
E/AndroidRuntime(16219):    at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:348)
E/AndroidRuntime(16219):    at android.app.Activity.dispatchActivityResult(Activity.java:5535)
E/AndroidRuntime(16219):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3600)
E/AndroidRuntime(16219):    ... 11 more
E/BTIF_GATT_CLIENT( 1375): [GATT][ERR] initGattcSock#1732 : bind socket failed : Invalid argument, errno=22
E/AudioService(  662): handleConfigurationChanged() createInstance IAudioServiceExt fail
E/bt_gap_api.c( 1375): [GAP]read error(0 bytes read) 11: Try again
E/BluetoothServiceJni( 1375): SOCK FLAG = 1 ***********************
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/BluetoothServiceJni( 1375): SOCK FLAG = 1 ***********************
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61460][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61460][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/BluetoothReceiver(  962): [MMI][BluetoothReceiver.startService][start service [com.mediatek.bluetooth.AdvancedService]
E/BluetoothServiceJni( 1375): SOCK FLAG = 0 ***********************
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61460][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61462][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/MTKBT   ( 1375): [Session]the session[61458][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61460][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]the session[61462][1375] is not ready to monitor
E/MTKBT   ( 1375): [Session]no any more session is in list
E/        (  733): appName=com.android.systemui, acAppName=/system/bin/surfaceflinger
E/        (  733): 0
E/        (  733): appName=com.android.systemui, acAppName=/system/bin/surfaceflinger
E/        (  733): 0
ghost commented 8 years ago

@qpwr Many thanks for the log. Looks like a null-pointer exception, but I don't see anything obvious in the code.

Does this happen in Evothings Viewer or in a "stand-alone" Cordova app? Do you have the version number for the Viewer or the plugin version?

qpwr commented 8 years ago

It does happen in my standalone app with this version of your plugin: cordova-plugin-ble 1.3.1 "Evothings BLE API"

ghost commented 8 years ago

@qpwr Hello again, there is now an updated version of the plugin version 1.4.0 that has checks for the null pointer exceptions.

Just a thought, can you check that startScan (or connect) is not called twice in your code, this may be the cause of the double dialog display.

Updated version of Evothings Viewer for Android:

https://evothings.com/uploads/evothings-studio/viewer/EvothingsViewer_1.4.1_debug_160705_2056.apk

Updated BLE plugin version 1.4.0:

https://github.com/evothings/cordova-ble/releases/tag/1.4.0

Updated EasyBLE library:

https://github.com/evothings/evothings-libraries/blob/master/libs/evothings/easyble/easyble.js

qpwr commented 8 years ago

Hey @mikaelkindborg, thanks for the new version. While it seems that the null pointer exception handling works (no more crashes when bluetooth is being requested), I'm no longer able to connect to my device properly (which used to work of course with 1.3.1). I'm currently doing this after successfully connecting to the device:

device.writeDescriptor(
    '39df9999-b1b4-b90b-57f1-7144ae4e4a6a', // characteristic
    '00002902-0000-1000-8000-00805f9b34fb', // descriptor
    new Uint8Array([1,0]),
    function() {
    },
    function() {
    }
);

device.enableNotification(
    '39df9999-b1b4-b90b-57f1-7144ae4e4a6a',
    function(data) {
        var realdata = new Uint8Array(data);
        app.util.parse_notification(realdata);
    },
    function() {
    }
);

This code worked with 1.3.1 of your plugin. Afterwards I'm requesting data like this:

ns.send_command = function(command) {

    if (!$.isFunction(app.net.device_handle.writeCharacteristic)) {
        return false;
    }

    app.net.device_handle.writeCharacteristic(
        "39df8888-b1b4-b90b-57f1-7144ae4e4a6a", // characteristic
        app.util.string_to_arraybuffer(ns.commands[command]),
        function() {
        },
        function() {
        }
    );
};

I added debug output to the writeCharacteristic call, but its never shown, which probably means that the function call fails internally. Do you have any clue for me? I also tried playing around with the new writeConfigDescriptor param, but to no avail... :-(

ghost commented 8 years ago

@qpwr Would be great to have some more debug logging to see what goes on. Did you add logging to the native Java code? Or to the JS code? The success and error callbacks in the above code are empty, have you tried to add debug logging there? Perhaps an error callback is called somewhere? Did you also update easyble.js?

qpwr commented 8 years ago

@mikaelkindborg, I can try to provide some debug output later. Regarding your question: I had added console.log()s to the calls above but removed them when I posted the code here. Neither of them would display.

Also, I honestly don't understand your documentation in ble.js when trying to find out if my code is correct at all. E.g., I'm using readServices() which seems to work correctly but doesn't appear in your documentation or in ble.js (there is only services()). Also, when calling enableNotification(), it was formerly not required to provide a characteristicHandle, but now it seems it is required to do so.

Am I perhaps doing something generally wrong?

ghost commented 8 years ago

@qpwr Hi, I will try to help. File ble.js is the JavaScript API for the BLE plugin, it is a rather low-level API. Then the file easyble.js is a higher level API that is meant to handle some common tasks and make it easier to use the plugin.

If you use easyble.js, you normally don't use the functions in ble.js. Furthermore, ble.js is not explicitly included in index.html (it is included when cordova.js is included), but easyble.js must be explicitly included in index.html.

Here is documentation for ble.js: https://evothings.com/doc/lib-doc/module-cordova-plugin-ble.html

And this is the documentation for easyble.js: https://evothings.com/doc/lib-doc/evothings.easyble.html

For latest version of easyble.js, see file on GitHub (and included documentation comments):

https://github.com/evothings/evothings-libraries/blob/master/libs/evothings/easyble/easyble.js

Does this help at all to clarify? You are welcome to email me you code to mikael@evothings.com and I will have a look.

qpwr commented 8 years ago

@mikaelkindborg, thank you very much for the clarification. I didn't know my own code actually, of course I'm including easyble.js (older version), but forgot about it due to my own asset management :-D

Well, the version of easyble.js I am currently using doesn't have any dependencies (which is nice), but now it seems I have to include a whole bunch of files (the whole evothings lib), which I don't like. Do I get something wrong? Or is there a "standalone" version of easyble.js?

ghost commented 8 years ago

@qpwr You are hitting a regrettable design choice, there is no standalone version of easyble.js. You have to add several folders with JS files for everything to work. Files are included using asynchronous loading which makes it non-transparent which files you need to have.

Here is a zip-archive with the files you need: evothings.zip

In index.html you need to include these files (in addition to your own JS files):

<script src="cordova.js"></script>
<script src="libs/evothings/evothings.js"></script>
<script src="libs/evothings/easyble/easyble.js"></script>

It goes without saying that this is overly complicated. I am working on making distribution JS files that include everything needed, not using any async file loading. Also planning a tutorial about this.

Thanks for your input, the trouble you have experienced shows that the handling of Evothings libraries needs to be improved.

Best regards, Mikael

qpwr commented 8 years ago

Thanks for giving some light on this. Would you recommend that i use the low level api (ble.js) then? I think I would Need to change how my code currently Works then, but it would probably be better.

ghost commented 8 years ago

@qpwr I recommend easyble.js since this is a easier (in my experience) than using the API in ble.js. The tricky thing with using the API in ble.js is that you need to manage mappings from UUIDs to handles for service characteristics and descriptors.

If you want to use ble.js (and not easyble.js) the function readAllServiceData in ble.js may be helpful.

ghost commented 8 years ago

@qpwr Hi again, here is a file called easyble.dist.js that contains all JavaScript needed for EasyBLE:

https://github.com/evothings/evothings-libraries/blob/master/libs/evothings/eddystone/eddystone.dist.js

Raw text:

https://raw.githubusercontent.com/evothings/evothings-libraries/master/libs/evothings/eddystone/eddystone.dist.js

No need to keep track of library folders.

Just include in your app (in index.html):

<script src="eddystone.dist.js"></script>

This file can be placed where you like, no need for it to be in an evothings folder.

Let me know how it works if you test this, just committed this update for testing.

qpwr commented 8 years ago

Thanks a lot @mikaelkindborg, I will definately try that.

ghost commented 8 years ago

@qpwr I just discovered a bug that prevented automatic writing of the config descriptor from working when enabling notifications/indications.

The options parameter should also work now.

Published a new BLE plugin version 1.4.1 with a fix.

Sorry for the trouble.

ghost commented 8 years ago

Release candidate of Evothings Viewer 1.4.1 for Android for testing available here:

https://evothings.com/uploads/evothings-studio/viewer/EvothingsViewer_1.4.1_160711_1608.apk

Contains the BLE plugin 1.4.1 with the bug fix for notifications.

qpwr commented 8 years ago

1.4.1 in connection with eddystone.dist.js (aka easyble.js) works smoothly for me. Thanks a lot, @mikaelkindborg. By the way: Is https://raw.githubusercontent.com/evothings/evothings-libraries/master/libs/evothings/eddystone/eddystone.dist.js also part of new releases, so I can be sure that I don't miss any bugfixes using this file?

ghost commented 8 years ago

@qpwr The EasyBLE library (easyble.dist.js) and the Eddystone library (eddystone.dist.js) are updated with bug fixes etc separately from the BLE plugin. We are in the process of putting these libraries under structured version handling. I am looking at ways to improve the whole BLE API-situation. It can be confusing to have both the BLE plugin and libraries written on top or the plugin. It has been an ongoing discussion whether to have libraries separated from the BLE plugin or include them with the BLE plugin. Bundling libraries with the BLE plugin, or updating the BLE plugin API itself to be easier to use, is certainly an option. Many thanks for your input, most valuable feedback!

qpwr commented 8 years ago

Well, I also would prefer as less dependencies as possible. So if it would be possible to have all the stuff in the plugin, I would be very happy. Keep up the great work and thanks a lot for your quick help :-)

ghost commented 8 years ago

@qpwr Many thanks for the feedback!

Just to let you know, there is a new release of the BLE plugin:

https://github.com/evothings/cordova-ble/releases

And a build of Evothings Viewer for Android with that plugin version included:

https://evothings.com/uploads/evothings-studio/viewer/EvothingsViewer_1.4.1_160712_1927.apk

qpwr commented 8 years ago

@mikaelkindborg, thanks for letting me know. Can you extend a bit on what this fix is about? I just released a new version of my app with 1.4.1 of your plugin and would like to know if I'm affected by the issue(s) you fixed. Thanks!

ghost commented 8 years ago

@qpwr It was the options parameter for enbleNotification that did not work properly. This caused failure to write characteristics when automatic writing of the config descriptor was turned off. If you haven't used the option writeConfigDescriptor: false it should work fine.

ghost commented 8 years ago

Closing this issue, let me know if any problems persist and I will reopen.