Communication Between Wear and Mobile.

Communication Between Wear and Mobile.

We have seen basic app development in last blog, Now In this blog we will see how data passes between wear to mobile and mobile to wear. In Application there are two packages Mobile and Wear with two separate Android apps, Both devices establish connection via Bluetooth link. Google play service allows access to establish data communication link between two devices. Below Diagram shows that how data move from one stack to another stack.

 

 

In this diagram mobile send a message using Wearable.MessageApi. Data layer and Bluetooth helps message to pass mobile to wear. On receiving area, there is method WearableListenerService , that get the message via invoking method onMessageReceived. It is very easy to implement.

 

 

1. Mobile Side Implementation
In below section we can see how mobile side implementation will be done in “Mobile” module.

 

Build Dependencies
Add the following build dependencies to the build.gradle file (Module:mobile) in the Gradle Scripts folder .

dependencies {
wearApp project(':wear')
implementation 'com.google.android.gms:play-services-wearable:+'
}

Metadata for play services in Manifest

<application>
...
<meta-data android:name="com.google.android.gms.version"
   android:value="@integer/google_play_services_version" />
</application>

Send Message
Here we have one example in which there is one button, It handles play and pause the animation object in wear. Now we will learn that how button sends play or pause command to the wear.

 

> First we have to create Google Play Services client

class MainActivity : AppCompatActivity(), GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener {
    private var mGoogleApiClient: GoogleApiClient? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mGoogleApiClient = GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build()
     }
     override fun onDestroy() {
        super.onDestroy()
     }
     override fun onStart() {
        super.onStart()
        mGoogleApiClient!!.connect()
     }
     override fun onConnected(p0: Bundle?) {
     }
     override fun onConnectionSuspended(p0: Int) {
     }
     override fun onConnectionFailed(p0: ConnectionResult) {
     }
     // other stuff
}

> Now Define the one Asynctask Threads class to send Message.
StartWearableActivityTask thread class implements method that sends message to all active nodes which are connected to data layer.This class runs in background thread.

@SuppressLint("StaticFieldLeak")
inner class StartWearableActivityTask internal constructor(internal var text: String) : AsyncTask<Void, Void, Boolean>() {
    override fun doInBackground(vararg args: Void): Boolean? {
        val flag: Boolean
        val nodes = getAllNodes()
        if (nodes.isEmpty()) {
            flag = false
        } else {
            flag = true
            for (node in nodes) {
                sendStringMessageToWear(node, text)
            }
        }
        return flag
    }
}

getAllNodes() is the method that fetch all the active nodes or connection devices, Means it fetch how many nodes are connected with our mobile. We get all the connection nodes only after google api client successfully established.

fun getAllNodes(): Collection {
    val results = HashSet()
    val nodeListTask = Wearable.getNodeClient(applicationContext).connectedNodes
    try {
        val nodes = Tasks.await(nodeListTask)
        for (node in nodes) {
            results.add(node.id)
        }
    } catch (exception: ExecutionException) {
    } catch (exception: InterruptedException) {
    }
    return results
}

sendStringMessageToWear() is the method which contains the message, node and key. Here we can see the key “/send-to-wear”, It will be handled by receiver side (wear) and Message will be send in toByteArray() format.

fun sendStringMessageToWear(node: String, message: String) {
    val sendMessageTask = Wearable
            .getMessageClient(applicationContext)
            .sendMessage(node, "/send-to-wear", message.toByteArray())
    try {
        val result = Tasks.await(sendMessageTask)
        
    } catch (exception: ExecutionException) {
    } catch (exception: InterruptedException) {
    }
}

> Full source code of Mainactivity.kt

package com.gmits.twowayconnection
import android.annotation.SuppressLint
import android.os.AsyncTask
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.tasks.Tasks
import com.google.android.gms.wearable.Wearable

import java.util.HashSet
import java.util.concurrent.ExecutionException

class MainActivity : AppCompatActivity(),
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    lateinit var ivPlay: ImageView
    private var mGoogleApiClient: GoogleApiClient? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mGoogleApiClient = GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build()
        resolveNode("Hello from mobile")
    }
   
    override fun onDestroy() {
        super.onDestroy()
       
    }
    override fun onStart() {
        super.onStart()
        mGoogleApiClient!!.connect()
     
    }
    private fun resolveNode(tag: String) {
        StartWearableActivityTask(tag).execute()
    }
    @SuppressLint("StaticFieldLeak")
    inner class StartWearableActivityTask internal constructor(internal var text: String) : AsyncTask<Void, Void, Boolean>() {
        override fun doInBackground(vararg args: Void): Boolean? {
            val flag: Boolean
            val nodes = getAllNodes()
            if (nodes.isEmpty()) {
                flag = false
            } else {
                flag = true
                for (node in nodes) {
                    sendStringMessageToWear(node, text)
                }
            }
            return flag
        }
    }
    fun getAllNodes(): Collection {
        val results = HashSet()
        val nodeListTask = Wearable.getNodeClient(applicationContext).connectedNodes
        try {
            val nodes = Tasks.await(nodeListTask)
            for (node in nodes) {
                results.add(node.id)
            }
        } catch (exception: ExecutionException) {
        } catch (exception: InterruptedException) {
        }
        return results
    }
    fun sendStringMessageToWear(node: String, message: String) {
        val sendMessageTask = Wearable
                .getMessageClient(applicationContext)
                .sendMessage(node, "/send-to-wear", message.toByteArray())
        try {
            val result = Tasks.await(sendMessageTask)
        } catch (exception: ExecutionException) {
        } catch (exception: InterruptedException) {
        }
    }
    override fun onConnected(p0: Bundle?) {
    }
    override fun onConnectionSuspended(p0: Int) {
    }
    override fun onConnectionFailed(p0: ConnectionResult) {
    }
}

2. Wear Side Implementation

This section explains how fetch message from sender. We have to put some configuration to “Wear” Module.

 

Build Dependencies

dependencies {
    implementation 'com.google.android.support:wearable:2.3.0'
    implementation 'com.google.android.gms:play-services-wearable:15.0.1'
    implementation 'com.android.support:wear:28.0.0-rc02'
    compileOnly 'com.google.android.wearable:wearable:2.3.0'
}

Add Listener Service to Wear Manifest

<uses-feature android:name="android.hardware.type.watch" />
<application
  ...
  <service android:name=".WearableMessageReceiver">
    <intent-filter>
      <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
      <data android:scheme="wear" android:host="*" android:pathPrefix="/send-to-wear" />
    </intent-filter>
  </service>
</application>

android:pathPrefix is the key which we mentioned above. Here key is “send-to-wear” which contains the message.

 

Listener Service Class

@SuppressLint("Registered")
class WearableMessageReceiver : WearableListenerService() {
    override fun onMessageReceived(messageEvent: MessageEvent?) {
        super.onMessageReceived(messageEvent)
    }
}

Get the Message in Wear

@SuppressLint("Registered")
class WearableMessageReceiver : WearableListenerService() {
    override fun onMessageReceived(messageEvent: MessageEvent?) {
        super.onMessageReceived(messageEvent)
        if (messageEvent!!.path.equals("/send-to-wear", ignoreCase = true)) {
            val s = String(messageEvent.data)
            Log.d(TAG, "Message received " + messageEvent.path + "& data: " + s)
        }
    }
}

Here, We get the message from mobile side, Here we put the condition weather path is “/send-to-wear” or not. If true then we can print the message in Log. If we want to pass message from wear to mobile same above process will be proceed in vice-versa. In below Github example I have implemented two way communication between wear and mobile so find out below repository and fork.

 

 

Here, You find the full source code.

https://github.com/Goldenmace/Mobile-To-Wear-and-Wear-To-Mobile-Communication

 

No Comments

Sorry, the comment form is closed at this time.