guy-keller / cordova-wearos-plugin

Simple plugin that establishes a session with a WearOs Smartwach and helps exchange of messages between a cordova application and its WearOs Watch application and vice-versa.
2 stars 3 forks source link

Data from watch is not being received in phone #2

Closed swetha-thoomoju closed 4 years ago

swetha-thoomoju commented 4 years ago

Hi,

When I send data from watch its not received in phone.

So I have done some debugging. Removed dependency on AAR file by creating new plugin using source code.

These are the logs from phone, changed the format to Bold for suspected logs.

2019-12-09 01:54:51.833 22892-22892/com.phonegap.helloworld I/chromium: [INFO:CONSOLE(47)] "Received Event: deviceready", source: file:///android_asset/www/js/index.js (47) 2019-12-09 01:54:51.835 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: constructor 2019-12-09 01:54:51.836 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: initialize 2019-12-09 01:54:51.836 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 01:54:51.836 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: init 2019-12-09 01:54:51.837 1374-1864/? W/ActivityManager: Unable to start service Intent { flg=0x20000000 cmp=com.phonegap.helloworld/com.github.guikeller.cordova.wearos.WearOsListenerService } U=0: not found 2019-12-09 01:54:51.838 22892-22975/com.phonegap.helloworld I/WearOsServiceConnection: constructor 2019-12-09 01:54:53.843 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 01:54:53.844 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: sendMessage :: args: [{"message":"hello from phone","value":"1234","foo":"bar"}] 2019-12-09 01:54:53.845 22892-22975/com.phonegap.helloworld I/WearOsMessageSender: constructor 2019-12-09 01:54:53.948 22892-22975/com.phonegap.helloworld W/PluginManager: THREAD WARNING: exec() call to CordovaWearOsPlugin.sendMessage blocked the main thread for 105ms. Plugin should use CordovaInterface.getThreadPool(). 2019-12-09 01:54:53.950 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 01:54:53.951 22892-22975/com.phonegap.helloworld I/CordovaWearOsPlugin: registerMessageListener :: listener: org.apache.cordova.CallbackContext@20785ca 2019-12-09 01:54:51.839 1374-1864/? W/ActivityManager: Unable to start service Intent { flg=0x20000000 cmp=com.phonegap.helloworld/com.github.guikeller.cordova.wearos.WearOsListenerService } U=0: not found 2019-12-09 01:55:15.579 22892-22914/com.phonegap.helloworld D/OpenGLRenderer: endAllActiveAnimators on 0x75d026bf00 (RippleDrawable) with handle 0x7644818040

The following logs should have been executed but do not find them in the logs:

    Log.i(TAG,"createWearOsMessageListener");
     Log.i(TAG,"onServiceConnected :: service: "+service);
     Log.i(TAG,"getService")

PS : New to native android development. Is there any better way to debug the issue. To understand the code and to enable breakpoints in Android Studio I removed dependency of AAR file.

guy-keller commented 4 years ago

Hi @swetha-thoomoju

Following below some suggestions:

The wear app and mobile app have to have the same version name. The wear app and mobile app have to have sequential version code numbers.

mobile app
versionName: "1.6.4"
versionCode: 10604001

wear app
versionName: "1.6.4"
versionCode: 10604002

In addition to the above, have a look on: #1 There I explain how to create a listener on the WearOs side - which is also on the README of the plugin.

This plugin is currently being used in my own mobile app that is available on the Play Store.

guy-keller commented 4 years ago

Also just to add here for historical purposes:

This that you are seeing: W/ActivityManager: Unable to start service Intent { flg=0x20000000 cmp=com.phonegap.helloworld/com.github.guikeller.cordova.wearos.WearOsListenerService } U=0: not found

It is happening because on your AndroidManifest.xml you did not add a service: https://github.com/guikeller/cordova-wearos-plugin-source/blob/master/app/src/main/AndroidManifest.xml

Hope this gives you some help/guidance.

swetha-thoomoju commented 4 years ago

Hi @guikeller,

Thanks for the inputs, you are right the service was not added to the AndroidManifest.xml. I was thinking it would have been added after installing the plugin, not sure how it got missed.

I know the plugin should work and I am trying figure what am missing. I have followed your instruction from #1. Can you tell the app name in Play Store.

Here is the issue log, facing Null pointer exemption

2019-12-09 12:41:39.161 32409-32409/com.phonegap.helloworld I/chromium: [INFO:CONSOLE(47)] "Received Event: deviceready", source: file:///android_asset/www/js/index.js (47) 2019-12-09 12:41:39.165 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: constructor 2019-12-09 12:41:39.165 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: initialize 2019-12-09 12:41:39.165 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 12:41:39.166 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: init 2019-12-09 12:41:39.169 32409-32506/com.phonegap.helloworld I/WearOsServiceConnection: constructor 2019-12-09 12:41:39.176 32409-32409/com.phonegap.helloworld I/WearOsListenerService: constructor 2019-12-09 12:41:44.183 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 12:41:44.183 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: sendMessage :: args: [{"message":"hello from phone","value":"1234","foo":"bar"}] 2019-12-09 12:41:44.184 32409-32506/com.phonegap.helloworld I/WearOsMessageSender: constructor 2019-12-09 12:41:44.269 32409-32506/com.phonegap.helloworld W/PluginManager: THREAD WARNING: exec() call to CordovaWearOsPlugin.sendMessage blocked the main thread for 87ms. Plugin should use CordovaInterface.getThreadPool(). 2019-12-09 12:41:44.271 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: execute 2019-12-09 12:41:44.272 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: registerMessageListener :: listener: org.apache.cordova.CallbackContext@a057ded 2019-12-09 12:41:44.272 32409-32506/com.phonegap.helloworld I/CordovaWearOsPlugin: createWearOsMessageListener 2019-12-09 12:41:44.272 32409-32506/com.phonegap.helloworld I/WearOsServiceConnection: getService 2019-12-09 12:41:44.274 32409-32506/com.phonegap.helloworld E/PluginManager: Uncaught exception from plugin java.lang.NullPointerException: Attempt to invoke virtual method 'void com.github.guikeller.cordova.wearos.WearOsListenerService.registerMessageListener(com.github.guikeller.cordova.wearos.WearOsMessageListener)' on a null object reference at com.github.guikeller.cordova.wearos.CordovaWearOsPlugin.registerMessageListener(CordovaWearOsPlugin.java:87) at com.github.guikeller.cordova.wearos.CordovaWearOsPlugin.execute(CordovaWearOsPlugin.java:52) at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:98) at org.apache.cordova.PluginManager.exec(PluginManager.java:132) at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:59) at org.apache.cordova.engine.SystemExposedJsApi.exec(SystemExposedJsApi.java:41) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:336) at android.os.Looper.loop(Looper.java:174) at android.os.HandlerThread.run(HandlerThread.java:67) 2019-12-09 12:41:44.279 32409-32409/com.phonegap.helloworld D/SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 61 : Message sent successfully! 2019-12-09 12:41:44.279 32409-32409/com.phonegap.helloworld I/chromium: [INFO:CONSOLE(61)] "Message sent successfully!", source: file:///android_asset/www/js/index.js (61) 2019-12-09 12:41:44.279 32409-32409/com.phonegap.helloworld D/SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 56 : Could not receive message from Watch 2019-12-09 12:41:44.279 32409-32409/com.phonegap.helloworld I/chromium: [INFO:CONSOLE(56)] "Could not receive message from Watch", source: file:///android_asset/www/js/index.js (56)

My observation is that binding in initialisation is not happening properly. Still this log is missing. Log.i(TAG,"onServiceConnected :: service: "+service);

Tried to figure out why onServiceConnected is not triggered but do not find the cause yet !!!

swetha-thoomoju commented 4 years ago

There might me something wrong when am changing the source code to use java files instead of AAR file. I have committed my changes here, is this how it should be done?

When I use plugin with AAR file, I do see following log but not receiving any callback !!!!

2019-12-09 16:29:39.463 10857-10944/com.phonegap.helloworld I/WearOsListenerService: onMessageReceived

As I want to debug issue changed the AAR file to Java files but facing Null pointer exemption mentioned above

guy-keller commented 4 years ago

Hi @swetha-thoomoju

This is how I use the plugin:

WearOsPlugin.init(initSuccess => {
  // registers to receive messages
  window.setTimeout(() => {
    WearOsPlugin.registerMessageListener(msg => {
      window.alert('Received Msg: ' + JSON.stringify(msg));
    }, error1 => {
      alert('Error sending msg: ' + JSON.stringify(error1));
    });
  }, 1250);
  // sends a message
  window.setTimeout(() => {
    WearOsPlugin.sendMessage(sendSuccess => {
      window.alert('Message sent successfully! ');
    }, error2 => {
      window.alert('Error sending msg: ' + JSON.stringify(error2));
    }, 'My Message to send');
  }, 1850);
}, error3 => {
    window.alert('Error initializing: ' + JSON.stringify(error3));
});

It would be good if I could see your JS. Also, are you using the simulator or real devices to test this?

Cheers!

guy-keller commented 4 years ago

Hello @swetha-thoomoju

This is how I send a message from the watch to the mobile app:

    private static final String MESSAGE_PATH = "/cordova/plugin/wearos";

    // Assumption is made that the mobile and watch are paired and connected
    public void sendMessage(final String messageToSend) {
        Log.i(TAG, "sendMessage");
        NodeClient nodeClient = Wearable.getNodeClient(context);
        Task<List<Node>> connectedNodes = nodeClient.getConnectedNodes();
        connectedNodes.addOnCompleteListener(new OnCompleteListener<List<Node>>() {
            @Override
            public void onComplete(@NonNull Task<List<Node>> task) {
                List<Node> nodes = task.getResult();
                for(Node node : nodes) {
                    sendMessageToNode(node.getId(), messageToSend);
                }
            }
        });
    }

    protected void sendMessageToNode(String nodeId, String messageToSend) {
        Log.i(TAG, "sendMessageToNode");
        byte[] message = new String(messageToSend).getBytes();
        Wearable.getMessageClient(context).sendMessage(nodeId, MESSAGE_PATH, message);
    }

Also, on the AndroidManifest.xml of the watch app add the following:

<manifest ..shortened_for_brevity>

  <uses-feature android:name="android.hardware.type.watch" />

  <application ..shortened_for_brevity>
    ...
    <uses-library
            android:name="com.google.android.wearable"
            android:required="true" />
    ...
  </application>
</manifest>

The key things to note above are the 'uses-feature' and 'uses-library' tags.

I am interested in knowing how you progress. Thanks for raising this bug, it is helping improve the plugin docs.

swetha-thoomoju commented 4 years ago

Hi @guikeller ,

Thanks for the support , I am using the exact JS code provided in ReadMe and Watch side code provided in ReadMe and #1. AndroidManifest.xml of the watch app also has the tags you have mentioned. I will try using the JS code from this and let you know.

I wonder why the plugin works differently while using AAR file and while using Java files !!! Is it possible for you to check if there is anything wrong I have done while replacing the files? I have forked this repo and pushed my changes there

Am using real devices to test. I would like to check out your app on play store, could you tell its name?

guy-keller commented 4 years ago

Hi @swetha-thoomoju ,

Awesome, thanks for keeping me on the loop, I am happy to help where I can. Also, to be honest, I am just as puzzled as you on why this is not working yet.

The AAR also uses a Gradle file, please have a look at my comment on your forked repo. Did you also add the other suggested plugins to your project?

cordova plugin add cordova-plugin-androidx
cordova plugin add cordova-plugin-androidx-adapter
cordova plugin add cordova-android-play-services-gradle-release

You can also debug your Cordova app using Google Chrome - see below: https://software.intel.com/en-us/xdk/docs/using-remote-chrome-devtools-to-debug-android-cordova-apps

The app name is: "WavesTracker" - available on the PlayStore. I use this plugin to transfer user credentials from the mobile phone to the watch. Then the watch sends a message back to the phone to indicate that the info has been stored on the watch successfully (config complete).

guy-keller commented 4 years ago

Hi @swetha-thoomoju ,

Did you get the plugin to work? What was the culprit?

Cheers

guy-keller commented 4 years ago

People do tend to disappear once they get things to work

swetha-thoomoju commented 4 years ago

People do tend to disappear once they get things to work

Hi @guikeller,

My apologies for the delayed response. I missed notifications, my bad....

swetha-thoomoju commented 4 years ago

Hi @swetha-thoomoju ,

Did you get the plugin to work? What was the culprit?

Cheers

Sorry again.... : |

Not yet... I only have few speculations not the root cause. As priorities changed, I was unable to work on it. This time am determined to find the cause.

guy-keller commented 4 years ago

If you create a small project that I can clone ( MIT Licensed ) for both platforms (watch and mobile) I could try and help; I would use the project as a 'demo' for the plugin.

swetha-thoomoju commented 4 years ago

If you create a small project that I can clone ( MIT Licensed ) for both platforms (watch and mobile) I could try and help; I would use the project as a 'demo' for the plugin.

Sure, should be able to do that before Monday.

When I do registerMessageListener , I receive a success call back even when there NO watch paired with phone. Is this expected? In your existing project did do try sending any message other than "OK".

Thank you :)

swetha-thoomoju commented 4 years ago

Hi @guikeller,

I might have found the cause which might be concealing the issue in the plugin, please check my last commit in the following repo. https://github.com/swetha-thoomoju/cordova_wearos_example This contains the android (watch and mobile) platform code of the PhoneGap project.

Following is the repo for complete android native code (watch and mobile). https://github.com/swetha-thoomoju/android_wear_demo

Hope you will not face any build issues.

guy-keller commented 4 years ago

Hi @swetha-thoomoju

I will have a look at it this week, just one quick question. How are you testing this? On the emulator or on a device?

Cheers

swetha-thoomoju commented 4 years ago

Hi @guikeller ,

Am testing on device not on emulator.

Thanks.

swetha-thoomoju commented 4 years ago

Hi @guikeller,

Were you able to check out the code?

Thanks

swetha-thoomoju commented 4 years ago

Hi @guikeller ,

Hope everything is good there. Did you get any chance to look into https://github.com/guikeller/cordova-wearos-plugin/issues/2#issuecomment-581090181

Can you check on commit here https://github.com/swetha-thoomoju/cordova_wearos_example, is it not required?

Thanks.

guy-keller commented 4 years ago

Hi @swetha-thoomoju ,

I had a look at your projects, here are the issues that I have found.

  1. The wear app AndroidManifest.xml does not have the required uses-feature and uses-library
  2. Projects have different package names ( io.swetha.wear_demo VS com.phonegap.helloworld )
  3. Projects don't follow the 'version code' ( 1 VS 2 ) [ use 100 and 101]

These have been documented on the "README": 1 = https://github.com/guikeller/cordova-wearos-plugin#use-from-wearos-java (Step 4) 2 & 3 = https://github.com/guikeller/cordova-wearos-plugin#extra-info

Can you please make these changes and let me know how you go? I hope this helps and gets you going.

Cheers!

swetha-thoomoju commented 4 years ago

Hi @guikeller,

Looks like there is a little misunderstanding they are completely different projects each have its own watch side code. one is a Cordova project : cordova_wearos_example , its watch code is this In this project can you check this commit https://github.com/swetha-thoomoju/cordova_wearos_example/commit/fda2a53b3a4e8d7d835f65e5aedcaf05753cc001

another one is a complete native project : android_wear_demo, its watch code is this.

These repos are complete examples for the communication between watch and app only thing missing is sending a message from Watch to Phone.

Thanks

guy-keller commented 4 years ago

To send a message from the watch to the phone do the following:

    private static final String MESSAGE_PATH = "/cordova/plugin/wearos";

    // Assumption is made that the mobile and watch are paired and connected
    public void sendMessage() {
        Log.i(TAG, "sendMessage");
        final String messageToSend = "I am a message from the watch! The time is: " + new Date();
        NodeClient nodeClient = Wearable.getNodeClient(context);
        Task<List<Node>> connectedNodes = nodeClient.getConnectedNodes();
        connectedNodes.addOnCompleteListener(new OnCompleteListener<List<Node>>() {
            @Override
            public void onComplete(@NonNull Task<List<Node>> task) {
                List<Node> nodes = task.getResult();
                for(Node node : nodes) {
                    sendMessageToNode(node.getId(), messageToSend);
                }
            }
        });
    }

    protected void sendMessageToNode(String nodeId, String messageToSend) {
        Log.i(TAG, "sendMessageToNode");
        byte[] message = new String(messageToSend).getBytes();
        Wearable.getMessageClient(context).sendMessage(nodeId, MESSAGE_PATH, message);
    }

Then on your "activity_main.xml" make the "onClick" invoke the "sendMessage" method.

In addition to that, make the changes as recommended here: https://github.com/guikeller/cordova-wearos-plugin/issues/2#issuecomment-600926852

The recommendations are based on the official Google docs: https://developer.android.com/training/wearables/apps/packaging https://developer.android.com/training/wearables/apps/debugging

Let me know how you go, cheers. If you still struggling I will put up sample projects.

guy-keller commented 4 years ago

@swetha-thoomoju

Oops, looked at your commit and I think that you are right, the intention was to have the "callbackContext" as a instance variable so you'd register only once ever.

I will fix that and generate a new .aar - sorry it took me so long to see the actual problem and what needed fixing. I wonder how mine works though.. Anyways, cheers!

guy-keller commented 4 years ago

Hi all,

Would anyone be able to test the fix and confirm if it is working okay now? Thank you very much in advance.

Cheers 😄

swetha-thoomoju commented 4 years ago

@guikeller I don't have the device to test right now. I will try to test it asap.

As per my understanding, In your case whenever there is a message from a watch you always would receive a message saying "OK". Not sure if you can receive any message saying something like "Message from Watch.."

Thanks.

guy-keller commented 4 years ago

Hi @swetha-thoomoju

Nowhere in the plugin code, it sends a message "OK". I am not sure what you mean there.

Cheers!

guy-keller commented 4 years ago

Hi @swetha-thoomoju

Did you manage testing the fix? I really hope all is working fine now.

Cheers! 😄

swetha-thoomoju commented 4 years ago

Hi @guikeller,

Could not test yet, It might take some time due to lockdown here.

Thanks.

guy-keller commented 4 years ago

Hi @swetha-thoomoju

I have managed to replicate the bug! (not that is a good thing)

2019-12-09 12:41:44.274 32409-32506/com.phonegap.helloworld E/PluginManager: Uncaught exception from plugin
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.github.guikeller.cordova.wearos.WearOsListenerService.registerMessageListener(com.github.guikeller.cordova.wearos.WearOsMessageListener)' on a null object reference
at com.github.guikeller.cordova.wearos.CordovaWearOsPlugin.registerMessageListener(CordovaWearOsPlugin.java:87)
at com.github.guikeller.cordova.wearos.CordovaWearOsPlugin.execute(CordovaWearOsPlugin.java:52)

I don't really understand what was going on there with the 'registerMessageListener' so I ended up re-writing the 'MessageListener' tested and am using the latest version! My apologies that it took so long to get there.

Cheers, Gui

guy-keller commented 4 years ago

Fixed it here (source): https://github.com/guikeller/cordova-wearos-plugin-source/commit/7b401b3b360f6213277cd40afcda4a9fb2c034fb

Pushed here (plugin/aar): https://github.com/guikeller/cordova-wearos-plugin/commit/221fabc7676637f7d0e30dacbd281571145cf138

swetha-thoomoju commented 4 years ago

That's great 👍

On Sun, Aug 30, 2020 at 8:02 AM Gui Keller notifications@github.com wrote:

Closed #2 https://github.com/guikeller/cordova-wearos-plugin/issues/2.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/guikeller/cordova-wearos-plugin/issues/2#event-3706964025, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFADLCKZ3HVDX6ZB43DYCDDSDG24ZANCNFSM4JYA353Q .

guy-keller commented 4 years ago

Hi @swetha-thoomoju

If you have any issues please open a new bug/issue. Let's leave this one closed as I am confident that the plugin should work now.

Cheers! 😄

g-galli-CS commented 2 years ago

Hi @guikeller, I'm facing the same issue: Data sent from watch (samsung galaxy watch 4, wearOS 3) is not received by any phone (eg. OnePlus 5T, Android 10). The devices are properly connected and the watch recognizes the phone as connected node. The listener on the phone initializes and gets the 'OK' message as expected. Messages are sent from smartphone and recieved by smartwatch on the "/cordova/plugin/wearos" path, no problem there.

the code that sends messages form the watch is the following:

    private fun sendRequestForCardId() {
        if (androidPhoneNodeWithApp != null) {
            val payload: ByteArray = "ABC".toByteArray()
            val sendMessageTask =
                Wearable.getMessageClient(applicationContext)
                    .sendMessage(androidPhoneNodeWithApp!!.id, MESSAGE_PATH, payload)

            sendMessageTask.addOnCompleteListener {
                if (it.isSuccessful) {
                    Log.d("send1", "Message sent successfully " + it.isComplete)
                } else {
                    Log.d("send1", "Message failed.")
                    viewModel.setState(AppState.NoPhone())
                }
            }
        }
    }

Messages from watch trigger the "Message sent successfully " log, but my ionic app gets nothing. The code that should listen for the messages on the phone is taken directly form the example. I'm trying to run it as soon as the platform is ready. I've used it in the app.component.ts directly and now I've converted it to a service (see functions below) with no luck.

  sendMessage(message: String) {
    console.log("sending message to Watch : " + message);
    WearOsPlugin.sendMessage(
      this.sendMessageSuccess.bind(this),
      this.sendMessageFailure.bind(this),
      message
    );
}

  async receiveMessageSuccess(message) {
    console.log(WearOsPlugin);
    // Received a message
    //var value = JSON.stringify(message);
    console.log("Received message from Watch: " + message);
    if (message != null) {
      this.generateMessage().then( (payload) => {
        setTimeout(() => {
          // Sends a message through 'sendMessage' - it 'should be' connected now
          this.sendMessage(payload);
        }, 1250);
      });
    }
  }

  receiveMessageFailure() {
    console.log("Could not receive message from Watch");
  }

  // Sending Messages to Watch
  sendMessageSuccess() {
    console.log("Message sent successfully!");
  }
  sendMessageFailure() {
    console.log("Could not send message to Watch.");
  }

  // Initializing Session
  initWatchSuccess() {
    WearOsPlugin.registerMessageListener(
      this.receiveMessageSuccess.bind(this),
      this.receiveMessageFailure.bind(this)
    );
  }

  initWatchFailure() {
    console.log("Could not connect to Watch.");
  }

  registerCommandCallback() {
    console.log(this.device.manufacturer)  
    WearOsPlugin.init(
      this.initWatchSuccess.bind(this),
      this.initWatchFailure.bind(this)
    );
  }
guy-keller commented 2 years ago

Could you please put some console.log on those methods so you can see the data flow? Also, could you please provide the full log of the device?

Ideally need a repo to reproduce the issues. Going off code snippets and no logs makes it really hard to help.

Please create a new bug with the requested info. Cheers!