Galaxy Watch apps can supply a variety of options and companies, however the watch’s smaller measurement in comparison with a cellular gadget means there are limitations, together with fewer {hardware} assets and a smaller display screen.
To take advantage of the capabilities of a cellular gadget, you may develop a companion cellular software for the wearable software. The companion software handles advanced and resource-intensive duties whereas the wearable software offers a seamless expertise.
Previously in this series, we confirmed create a companion cellular software for a Galaxy Watch operating Put on OS powered by Samsung and use the Wearable Data Layer API to ship messages from the watch to the cellular gadget.
Whereas it’s straightforward to verify the watch’s battery stage from the cellular gadget, the reverse is extra advanced. This tutorial describes set up two-way communication between the wearable and cellular functions and use it to verify the cellular gadget’s battery stage from the watch.
Conditions
To develop a wearable software and its companion cellular software, create a multi-module challenge in Android Studio. The steps are described in the previous tutorial, and the identical dependencies and modifications are required for the wearable software on this tutorial:
- Add the next dependencies to the construct.gradle file
dependencies { ... implementation "com.google.android.gms:play-services-wearable:xx.x.x" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:x.x.x" implementation "androidx.lifecycle:lifecycle-extensions:x.x.x" implementation "androidx.lifecycle:lifecycle-runtime-ktx:x.x.x" implementation "androidx.appcompat:appcompat:x.x.x" }
- Modify the
MainActivity
class to inheritAppCompatActivity()
as a substitute ofExercise()
. - Within the “AndroidManifest.xml” file, within the
<software>
component, change theandroid:theme
attribute worth to “@type/Theme.AppCompat.NoActionBar” or one other customized theme.
WarningThe bundle IDs of the wearable and cellular functions should be equivalent.
To check the challenge, you want a Galaxy Watch operating Put on OS powered by Samsung and a related Galaxy cellular gadget.
Request battery info from the companion software
To have the ability to retrieve the cellular gadget’s battery stage as a proportion from the watch, the companion software on the cellular gadget should promote the “battery_percentage” functionality.
Within the cellular software, create an XML file named “put on.xml” within the “res/values/” listing with the next content material:
<!--XML configuration file-->
<?xml model="1.0" encoding="utf-8"?>
<assets xmlns:instruments="http://schemas.android.com/instruments"
instruments:preserve="@array/android_wear_capabilities">
<string-array title="android_wear_capabilities">
<merchandise>battery_percentage</merchandise>
</string-array>
</assets>
Whereas a watch may be related to just one gadget at a time, a cellular gadget may be related to a number of wearables on the similar time. To find out which node (related gadget) corresponds to the watch, use the CapabilityClient
class of the Wearable Data Layer API to retrieve all of the obtainable nodes and choose the perfect or closest node to ship your message.
// MainActivity class within the wearable software
non-public var batteryNodeId: String? = null
non-public enjoyable setupBatteryPercentage() {
// Retailer the reachable nodes
val capabilityInfo: CapabilityInfo = Duties.await(
Wearable.getCapabilityClient(applicationContext)
// Retrieve all related nodes with the 'battery_percentage' functionality
.getCapability(
BATTERY_PERCENTAGE_CAPABILITY_NAME,
CapabilityClient.FILTER_REACHABLE
)
)
// Use a listener to retrieve the reachable nodes
updateBatteryCapability(capabilityInfo).additionally { capabilityListener ->
Wearable.getCapabilityClient(this @MainActivity).addListener(
capabilityListener,
BATTERY_PERCENTAGE_CAPABILITY_NAME
)
}
}
non-public enjoyable pickBestNodeId(nodes: Set<Node>): String? {
// Discover the perfect node
return nodes.firstOrNull { it.isNearby }?.id ?: nodes.firstOrNull()?.id
}
non-public enjoyable updateBatteryCapability(capabilityInfo: CapabilityInfo) {
// Specify the recipient node for the message
batteryNodeId = pickBestNodeId(capabilityInfo.nodes)
}
companion object{
non-public const val TAG = "MainWearActivity"
non-public const val BATTERY_PERCENTAGE_CAPABILITY_NAME = "battery_percentage"
non-public const val BATTERY_MESSAGE_PATH = "/message_battery"
}
To implement bi-directional communication between watch and cellular gadget, you need to use the MessageClient
class of the Wearable Information Layer API.
Within the wearable software UI, create a button and a textView.
To show the cellular gadget’s battery stage on the textView when the button is tapped, implement the button’s onClickListener()
perform. Ship the battery stage request message by means of a particular message path to the cellular gadget, utilizing a coroutine that calls the setupBatteryPercentage()
and requestBatteryPercentage()
strategies on a separate thread. A separate thread should be used as a result of these are synchronous calls that block the UI thread.
// MainActivity class within the wearable software
non-public lateinit var binding: ActivityMainBinding
override enjoyable onCreate(savedInstanceState: Bundle?) {
tremendous.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
Log.d(TAG, "onCreate()")
binding.apply{
phoneButton.setOnClickListener{
lifecycleScope.launch(Dispatchers.IO){
setupBatteryPercentage()
requestBatteryPercentage("Battery".toByteArray())
}
}
}
}
// Ship the message to the chosen node
non-public enjoyable requestBatteryPercentage(knowledge: ByteArray) {
batteryNodeId?.additionally { nodeId ->
val sendTask: Process<*> = Wearable.getMessageClient(this @MainActivity).sendMessage(
nodeId,
BATTERY_MESSAGE_PATH,
knowledge
).apply {
addOnSuccessListener { Log.d(TAG, "OnSuccess") }
addOnFailureListener { Log.d(TAG, "OnFailure") }
}
}
}
Obtain the message on the companion software
The companion software should be capable of obtain and reply to the message from the background. To perform this, implement a service that listens for incoming messages.
Within the cellular software, create a category that extends WearableListenerService()
and add the service to the appliance manifest file:
<!--Android manifest file for the cellular application-->
<service
android:title=".PhoneListenerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<motion android:title="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<knowledge
android:host="*"
android:pathPrefix="https://developer.samsung.com/"
android:scheme="put on" />
</intent-filter>
</service>
Use the batteryManager
class to retrieve the present battery stage of the gadget. To ship the retrieved worth again to the wearable software, use the sendMessage()
perform once more. For simplicity, ship the message to the primary related node on the cellular gadget. Alternatively, you may broadcast to all related nodes.
Implement the OnMessageReceived()
perform to obtain the incoming request for battery stage and ship the retrieved worth to the wearable software.
// Service class within the cellular software
non-public val scope = CoroutineScope(SupervisorJob() + Dispatchers.Most important.speedy)
non-public var batteryNodeId: String? = null
override enjoyable onDestroy() {
scope.cancel()
tremendous.onDestroy()
}
override enjoyable onMessageReceived(messageEvent: MessageEvent) {
Log.d(TAG, "onMessageReceived(): $messageEvent")
Log.d(TAG, String(messageEvent.knowledge))
if (messageEvent.path == BATTERY_MESSAGE_PATH && String(messageEvent.knowledge) == "Battery") {
// Test that the request and path are appropriate
val batteryManager = applicationContext.getSystemService(BATTERY_SERVICE) as BatteryManager
val batteryValue:Int = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
scope.launch(Dispatchers.IO){
// Ship the message to the primary node
batteryNodeId = getNodes().first()?.additionally { nodeId->
val sendTask: Process<*> = Wearable.getMessageClient(applicationContext).sendMessage(
nodeId,
BATTERY_MESSAGE_PATH,
batteryValue.toString().toByteArray()
).apply {
addOnSuccessListener { Log.d(TAG, "OnSuccess") }
addOnFailureListener { Log.d(TAG, "OnFailure") }
}
}
}
}
onDestroy()
}
non-public enjoyable getNodes(): Assortment<String> {
return Duties.await(Wearable.getNodeClient(this).connectedNodes).map { it.id }
}
companion object{
non-public const val TAG = "PhoneListenerService"
non-public const val BATTERY_MESSAGE_PATH = "/message_battery"
}
Show the battery info on the wearable software
When receiving the battery info on the wearable software, as a result of the consumer is actively interacting with the appliance, a resource-intensive service is just not wanted and registering a reside listener is adequate. Use the addListener()
methodology of the MessageClient
class to implement the MessageClient.OnMessageReceivedListener
interface inside the MainActivity
class within the wearable software.
// MainActivity class within the wearable software
override enjoyable onResume(){
tremendous.onResume()
Log.d(TAG, "onResume()")
// Wearable API shoppers are usually not resource-intensive
Wearable.getMessageClient(this).addListener(this)
}
override enjoyable onPause(){
tremendous.onPause()
Log.d(TAG, "onPause()")
Wearable.getMessageClient(this).removeListener(this)
}
override enjoyable onMessageReceived(messageEvent: MessageEvent) {
// Obtain the message and show it
if(messageEvent.path == BATTERY_MESSAGE_PATH){
Log.d(TAG, "Cellular battery proportion: " + String(messageEvent.knowledge) + "%")
binding.phoneTextView.textual content = String(messageEvent.knowledge)
}
}
Conclusion
To check the challenge, construct each functions and run them in your Galaxy Watch and cellular gadget. Once you faucet the UI button on the watch, the appliance retrieves the battery stage from the cellular gadget and shows the share on the watch.
This demonstration has proven how the Wearable Information Layer API lets you implement seamless bi-directional communication between a Galaxy Watch operating Put on OS powered by Samsung and its related cellular gadget. Along with battery stage, you need to use the CapabilityClient
and MessageClient
courses to switch numerous knowledge between the units in an analogous manner.
For extra details about implementing communication between watch and cellular units, see Send and receive messages on Wear.
You probably have questions on or need assistance with the data on this tutorial, you may share your queries on the Samsung Developers Forum. For extra specialised assist, you may contact us by means of Samsung Developer Support.
Keep tuned for the following installment on this tutorial collection.