Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

two-way messaging between phone and wearos #2

Merged
merged 6 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package com.wearconnectivity;

import android.util.Log;
import android.widget.Toast;
import static com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST;

import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
Expand All @@ -18,17 +23,19 @@
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeClient;
import com.google.android.gms.wearable.Wearable;

import java.util.List;
import java.util.concurrent.ExecutionException;

public class WearConnectivityModule extends WearConnectivitySpec implements MessageClient.OnMessageReceivedListener, LifecycleEventListener {
public class WearConnectivityModule extends WearConnectivitySpec
implements MessageClient.OnMessageReceivedListener, LifecycleEventListener {
public static final String NAME = "WearConnectivity";
private static final String TAG = "WearConnectivityModule";
private final MessageClient client;

WearConnectivityModule(ReactApplicationContext context) {
super(context);
context.addLifecycleEventListener(this);
Wearable.getMessageClient(context).addListener(this);
client = Wearable.getMessageClient(context);
client.addListener(this);
}

@Override
Expand All @@ -37,7 +44,6 @@ public String getName() {
return NAME;
}


// Example method
// See https://reactnative.dev/docs/native-modules-android
@ReactMethod
Expand All @@ -47,71 +53,76 @@ public void multiply(double a, double b, Promise promise) {

// catch the ExecutionException
@ReactMethod
public void increaseWearCounter(Promise promise) {
public void sendMessage(String path, Promise promise) {
try {
// add a check that it has permissions for that scope
// https://android-developers.googleblog.com/2017/11/moving-past-googleapiclient_21.html
NodeClient nodeClient = Wearable.getNodeClient(getReactApplicationContext());
List<Node> nodes = Tasks.await(nodeClient.getConnectedNodes());
if (nodes.size() > 0) {
for (Node node : nodes) {
sendMessageToClient(node);
sendMessageToClient(path, node);
}
promise.resolve(true);
} else {
Toast.makeText(getReactApplicationContext(), "No connected nodes found", Toast.LENGTH_LONG).show();
Toast.makeText(getReactApplicationContext(), "No connected nodes found", Toast.LENGTH_LONG)
.show();
}
} catch(Exception e) {
Log.w("TESTING", "EXCEPTION: " + e);
} catch (Exception e) {
FLog.w(TAG, " getConnectedNodes raised Exception: " + e);
}
}

private void sendMessageToClient(Node node) {
private void sendMessageToClient(String path, Node node) {
try {
Task<Integer> sendTask =
Wearable.getMessageClient(getReactApplicationContext()).sendMessage(
node.getId(), "/increase_wear_counter", null);
OnSuccessListener<Object> onSuccessListener = new OnSuccessListener<Object>() {
@Override
public void onSuccess(Object object) {
Log.w("TESTING: ", "from Phone onSuccess");
}
};
Wearable.getMessageClient(getReactApplicationContext())
.sendMessage(node.getId(), path, null);
OnSuccessListener<Object> onSuccessListener =
new OnSuccessListener<Object>() {
@Override
public void onSuccess(Object object) {
FLog.d(TAG, " sendMessage called onSuccess for path: " + path);
}
};
sendTask.addOnSuccessListener(onSuccessListener);
OnFailureListener onFailureListener = new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w("TESTING: ", "from Phone onFailure with e: " + e);
}
};
OnFailureListener onFailureListener =
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
FLog.d(TAG, " sendMessage called onFailure with error: " + e);
}
};
sendTask.addOnFailureListener(onFailureListener);
} catch (Exception e) {
Log.w("TESTING: ", "from Phone e: " + e);
FLog.w(TAG, " sendMessage raised Exception: " + e);
}
}

public void onMessageReceived(MessageEvent messageEvent) {
Log.w("TESTING: ", "from Phone onMessageReceived");
/*
if (messageEvent.getPath().equals("/increase_phone_counter")) {
sendEvent(getReactApplicationContext(), "increaseCounter", null);
}
*/
FLog.d(TAG, " onMessageReceived called for path: " + messageEvent.getPath());
sendEvent(getReactApplicationContext(), messageEvent.getPath(), null);
}

private void sendEvent(
ReactContext reactContext, String eventName, @Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}

@Override
public void onHostResume() {
// implement it
if (client != null) {
client.addListener(this);
}
}


@Override
public void onHostPause() {
// implement it
client.removeListener(this);
}

@Override
public void onHostDestroy() {
Wearable.getMessageClient(getReactApplicationContext()).removeListener(this);
client.removeListener(this);
}
}
2 changes: 1 addition & 1 deletion android/src/oldarch/WearConnectivitySpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ abstract class WearConnectivitySpec extends ReactContextBaseJavaModule {
}

public abstract void multiply(double a, double b, Promise promise);
public abstract void increaseWearCounter(Promise promise);
public abstract void sendMessage(String path, Promise promise);
}
17 changes: 10 additions & 7 deletions example/src/WearScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
import {
DeviceEventEmitter,

Check failure on line 3 in example/src/WearScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'DeviceEventEmitter' is defined but never used
NativeEventEmitter,
View,
StyleSheet,
Expand All @@ -8,9 +8,10 @@
NativeModules,
Button,
} from 'react-native';
import { multiply, increaseWearCounter } from 'react-native-wear-connectivity';
import { multiply, sendMessage } from 'react-native-wear-connectivity';

Check failure on line 11 in example/src/WearScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'multiply' is defined but never used

const INCREASE_COUNTER_EVENT = 'increaseCounter';
const INCREASE_PHONE_COUNTER_EVENT = 'increase_phone_counter';
const INCREASE_WEAR_COUNTER_EVENT = 'increase_wear_counter';

export default function WearCounter() {
const [count, setCount] = React.useState(0);
Expand All @@ -19,18 +20,20 @@
const eventEmitter = new NativeEventEmitter(
NativeModules.AndroidWearCommunication
);
let eventListener = eventEmitter.addListener(INCREASE_COUNTER_EVENT, () => {
setCount((prevCount) => prevCount + 1);
});
let eventListener = eventEmitter.addListener(
INCREASE_PHONE_COUNTER_EVENT,
() => {
setCount((prevCount) => prevCount + 1);
}
);

return () => {
eventListener.remove();
};
}, []);

const onPressHandler = () => {
console.log('onPressHandler');
increaseWearCounter();
sendMessage(INCREASE_WEAR_COUNTER_EVENT);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion src/NativeWearConnectivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TurboModuleRegistry } from 'react-native';

export interface Spec extends TurboModule {
multiply(a: number, b: number): Promise<number>;
increaseWearCounter(): Promise<boolean>;
sendMessage(path: string): Promise<boolean>;
}

export default TurboModuleRegistry.getEnforcing<Spec>('WearConnectivity');
4 changes: 2 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ export function multiply(a: number, b: number): Promise<number> {
return WearConnectivity.multiply(a, b);
}

export function increaseWearCounter(): Promise<boolean> {
return WearConnectivity.increaseWearCounter();
export function sendMessage(path: string): Promise<boolean> {
return WearConnectivity.sendMessage(path);
}
40 changes: 33 additions & 7 deletions watch-example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
import * as React from 'react';
import React, { useEffect, useState } from 'react';

import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
import { multiply } from 'react-native-wear-connectivity';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
NativeEventEmitter,
NativeModules,
} from 'react-native';
import { multiply, sendMessage } from 'react-native-wear-connectivity';

const INCREASE_WEAR_COUNTER_EVENT = 'increase_wear_counter';
const INCREASE_PHONE_COUNTER_EVENT = 'increase_phone_counter';

export default function App() {
const [result, setResult] = React.useState<number | undefined>();
const [count, setCount] = React.useState(0);
const [result, setResult] = useState<number | undefined>();

Check failure on line 17 in watch-example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

'result' is assigned a value but never used. Allowed unused elements of array destructuring patterns must match /^_/u
const [count, setCount] = useState(0);

React.useEffect(() => {
useEffect(() => {
multiply(3, 7).then(setResult);
}, []);

useEffect(() => {
const eventEmitter = new NativeEventEmitter(
NativeModules.AndroidWearCommunication
);
let eventListener = eventEmitter.addListener(
INCREASE_WEAR_COUNTER_EVENT,
() => {
setCount((prevCount) => prevCount + 1);
}
);

return () => {
eventListener.remove();
};
}, []);

return (
<View style={styles.container}>
<Text>count is: {count}</Text>
<TouchableOpacity
onPress={() => setCount((currentCount) => currentCount + 1)}
onPress={() => sendMessage(INCREASE_PHONE_COUNTER_EVENT)}
style={styles.button}
/>
</View>
Expand Down
Loading