Skip to content

Commit

Permalink
Merge pull request #1 from fabOnReact/implement-watch-example
Browse files Browse the repository at this point in the history
Implement watch example and basic send message api
  • Loading branch information
fabOnReact authored Feb 8, 2024
2 parents 510bfc6 + 72e80ef commit aacade3
Show file tree
Hide file tree
Showing 67 changed files with 15,692 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ android/keystores/debug.keystore

# generated by bob
lib/
example/.env
watch-example/.env
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ dependencies {
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation 'com.google.android.gms:play-services-wearable:18.1.0'
}

if (isNewArchitectureEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
package com.wearconnectivity;

import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import com.google.android.gms.wearable.MessageClient;
import com.google.android.gms.wearable.MessageEvent;
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 {
public class WearConnectivityModule extends WearConnectivitySpec implements MessageClient.OnMessageReceivedListener, LifecycleEventListener {
public static final String NAME = "WearConnectivity";

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

@Override
Expand All @@ -26,4 +44,74 @@ public String getName() {
public void multiply(double a, double b, Promise promise) {
promise.resolve(a * b);
}

// catch the ExecutionException
@ReactMethod
public void increaseWearCounter(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);
}
promise.resolve(true);
} else {
Toast.makeText(getReactApplicationContext(), "No connected nodes found", Toast.LENGTH_LONG).show();
}
} catch(Exception e) {
Log.w("TESTING", "EXCEPTION: " + e);
}
}

private void sendMessageToClient(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");
}
};
sendTask.addOnSuccessListener(onSuccessListener);
OnFailureListener onFailureListener = new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.w("TESTING: ", "from Phone onFailure with e: " + e);
}
};
sendTask.addOnFailureListener(onFailureListener);
} catch (Exception e) {
Log.w("TESTING: ", "from Phone e: " + e);
}
}

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

@Override
public void onHostResume() {
// implement it
}


@Override
public void onHostPause() {
// implement it
}

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

public abstract void multiply(double a, double b, Promise promise);
public abstract void increaseWearCounter(Promise promise);
}
6 changes: 4 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "react-native-wear-connectivity-example",
"name": "react-native-phone-connectivity-example",
"version": "0.0.1",
"private": true,
"scripts": {
Expand All @@ -10,8 +10,10 @@
"build:ios": "cd ios && xcodebuild -workspace WearConnectivityExample.xcworkspace -scheme WearConnectivityExample -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO"
},
"dependencies": {
"@react-native-google-signin/google-signin": "^11.0.0",
"react": "18.2.0",
"react-native": "0.73.4"
"react-native": "0.73.4",
"react-native-config": "^1.5.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
26 changes: 16 additions & 10 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import * as React from 'react';

import { StyleSheet, View, Text } from 'react-native';
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import LoginScreen from './LoginScreen';
import WearScreen from './WearScreen';
import { GoogleSignin } from '@react-native-google-signin/google-signin';

Check failure on line 5 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

'GoogleSignin' is defined but never used
import { multiply } from 'react-native-wear-connectivity';

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

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

return (
<View style={styles.container}>
<Text>Result: {result}</Text>
</View>
<>
<LoginScreen />
<WearScreen />
<View style={styles.container}>
<Text>Result: {result}</Text>
</View>
</>
);
}
};

const styles = StyleSheet.create({
container: {
Expand All @@ -29,3 +33,5 @@ const styles = StyleSheet.create({
marginVertical: 20,
},
});

export default App;
31 changes: 31 additions & 0 deletions example/src/LoginScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import {
View,
StyleSheet,

Check failure on line 4 in example/src/LoginScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'StyleSheet' is defined but never used
Text,

Check failure on line 5 in example/src/LoginScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'Text' is defined but never used
TextInput,

Check failure on line 6 in example/src/LoginScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'TextInput' is defined but never used
NativeModules,

Check failure on line 7 in example/src/LoginScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

'NativeModules' is defined but never used
Button,
} from 'react-native';
import {GoogleSignin} from '@react-native-google-signin/google-signin';

Check failure on line 10 in example/src/LoginScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

Replace `GoogleSignin` with `·GoogleSignin·`
import Config from 'react-native-config';

export default function LoginScreen() {
const signIn = async () => {
try {
GoogleSignin.configure({
androidClientId: Config.GOOGLE_ANDROID_CLIENT_ID,
});
const userInfo = await GoogleSignin.signIn();
console.log(JSON.stringify(userInfo));
} catch (error) {
console.log('ERROR IS: ' + JSON.stringify(error));
}
};

return (
<View>
<Button title={'Sign in with Google'} onPress={signIn} />
</View>
);
}
58 changes: 58 additions & 0 deletions example/src/WearScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
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,
Text,
NativeModules,
Button,
} from 'react-native';
import { multiply, increaseWearCounter } 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';

export default function WearCounter() {
const [count, setCount] = React.useState(0);

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

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

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

return (
<View style={styles.container}>
<Text style={styles.counter}>{count}</Text>
<Button title="increase counter" onPress={onPressHandler} />
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 8,
backgroundColor: 'yellow',
},
counter: {
height: 100,
width: 400,
textAlign: 'center',
fontSize: 50,
fontWeight: 'bold',
},
});
14 changes: 0 additions & 14 deletions lefthook.yml

This file was deleted.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"!**/.*"
],
"scripts": {
"example": "yarn workspace react-native-wear-connectivity-example",
"example": "yarn workspace react-native-phone-connectivity-example",
"watch-example": "yarn workspace react-native-wear-connectivity-example",
"test": "jest",
"typecheck": "tsc --noEmit",
"lint": "eslint \"**/*.{js,ts,tsx}\"",
Expand Down Expand Up @@ -54,7 +55,6 @@
},
"devDependencies": {
"@commitlint/config-conventional": "^17.0.2",
"@evilmartians/lefthook": "^1.5.0",
"@react-native/eslint-config": "^0.72.2",
"@release-it/conventional-changelog": "^5.0.0",
"@types/jest": "^28.1.2",
Expand Down Expand Up @@ -83,7 +83,8 @@
"react-native": "*"
},
"workspaces": [
"example"
"example",
"watch-example"
],
"packageManager": "yarn@3.6.1",
"engines": {
Expand Down
1 change: 1 addition & 0 deletions src/NativeWearConnectivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TurboModuleRegistry } from 'react-native';

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

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

export function increaseWearCounter(): Promise<boolean> {
return WearConnectivity.increaseWearCounter();
}
2 changes: 2 additions & 0 deletions watch-example/.bundle/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1
1 change: 1 addition & 0 deletions watch-example/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
9 changes: 9 additions & 0 deletions watch-example/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source 'https://rubygems.org'

# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"

# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
Loading

0 comments on commit aacade3

Please sign in to comment.