watch-connectivity / react-native-watch-connectivity

Enable communication between apple watch app and react native
http://mtford.co.uk/react-native-watch-connectivity/
MIT License
710 stars 92 forks source link

Could this be used with Expo Prebuild? #121

Open markymc opened 1 year ago

markymc commented 1 year ago

Hi, first of all, thanks for your work on this library. I've found it very useful already.

I've been facing some build problems with my ejected Expo project recently, and came across Expo's recent suggestion to use Expo Prebuild instead of ejecting.

I was wondering if this library might be compatible with a bit of work?

Off the top of my head, for iOS support we'd need to:

  1. Create a config plugin that:
    1. Adds a watch target to the generated xcode workspace
    2. Includes any watch-related native files too

I'll try to look into this when I have time, but thought I'd get a conversation started in case anyone else has been thinking about it.

EDIT - this might have some examples to follow perhaps https://github.com/bndkt/react-native-app-clip/tree/main/plugin/src

yolpsoftware commented 1 year ago

This sounds very promising. Unfortunately, my Xcode knowledge is limited, so I'm not sure if I can help you. But please keep us posted, and I would be happy to help you test the plugin.

mtford90 commented 1 year ago

It's been a while since i've dealt with Expo but certainly looks like something we should support.

Not sure when I'll be able to look into this myself but it should certainly be on the roadmap - @markymc do feel free to have a crack at this yourself if you have the time - and feel free to reach out for support

markymc commented 1 year ago

OK thanks guys. To be honest, I worked out my build issues so my need for this is less immediate now. However, I would be happy to work on this when I have more free time. I'll let you know if/when that happens.

dylmye commented 9 months ago

This would be awesome.

CristiCeban commented 8 months ago

Hi, I've created a initial PR for that thing, you can check it here https://github.com/mtford90/react-native-watch-connectivity/pull/125 Please feel free to ask any question! Thanks

markymc commented 8 months ago

Wow, thank you so much, @CristiCeban! I won't have a chance to try this out for a while unfortunately, but I'll try to if the PR is still open when I get a chance (although if we're lucky it will be merged soon!).

yolpsoftware commented 8 months ago

Thank you so much @CristiCeban, if I'm lucky I will be able to try it out during the next few days.

yolpsoftware commented 8 months ago

@CristiCeban sorry if this is a basic question, but can I test the example using

"react-native-watch-connectivity": "git+https://github.com/CristiCeban/react-native-watch-connectivity#feat/expo-plugin"

in my package.json, or do I need to download the fork, build it and then reference the tgz file as in the watch-example demo? I tried it with the git+https://... option, but the imports do not work.

Generally, will this plugin work by just referencing its npm package?

dylmye commented 8 months ago

@yolpsoftware you'll need to build a local copy of the branch using yarn build and use something like yalc or yarn link to replace the react-native-watch-connectivity package

CristiCeban commented 8 months ago

Hello, I don't really know about git+https://github.com/CristiCeban/react-native-watch-connectivity#feat/expo-plugin, but from that I think the fork doesn't have a build folder, so maybe you don't have a js code transpilled there, that's why the imports don't work. I built the ts code locally and reference it via the local path (.tgz) I'll have a look if the imports don't work or if it's something else in build if referencing locally too

Generally, will this plugin work by just referencing its npm package? Yes, then it will be merged (or I will publish the fork in npm), it will just work via npm

CristiCeban commented 8 months ago

@yolpsoftware I checked "import" issue, the .d.ts file was not included in the build (it worked, but ts was yelling :) ), I fixed and updated my pr. Please be sure to test with latest changes. I also updated example app to use different icon (the icon before was slightly smaller that 1024 px, so xcode was yelling in another place at me), should be fine now

yolpsoftware commented 8 months ago

Thanks guys. I tried to add this to my existing Expo project (thought this would be a better test than to just re-compile your example project).

No success so far. This is what I tried:

Any hints welcome, but if these errors have nothing to do with the fork, I'll just wait until the fork is merged.

CristiCeban commented 8 months ago

@yolpsoftware Hey, could you please retry ?

  1. clone this repo https://github.com/CristiCeban/react-native-watch-connectivity (I updated it just now, so be sure to pull the last version)
  2. checkout to feat/expo-plugin branch
  3. run yarn install
  4. run yarn build- this will build the react-native-watch-package and it's in watch mode by default (I didn't found yet to disable watch mode, it's from expo). After you see this text you could cancel process
    
    [8:50:17 PM] Starting compilation in watch mode...

[8:50:18 PM] Found 0 errors. Watching for file changes.

5. run `yarn build plugin`. This will build the expo plugin for integrating watch. You'll see the same message as for step 4. When you'll see this message, stop the process
6. run `yarn pack` to pack this builded package
7. go to your expo project and open it in terminal. run `npm install path/to/generated/package/react-native-watch-connectivity-v1.1.0.tgz`. if you're using yarn run `yarn add path/to/generated/package/react-native-watch-connectivity-v1.1.0.tgz`  (when it will be published to npm you will skip all these steps and start with 8)
8. open `app.json` from your expo project, and add this lines from [here](https://github.com/CristiCeban/watch-example/blob/main/app.json#L14). change bundleId with bundle id of your app (Maybe I'll automatise it in the future)
```ts
 "plugins": [
      [
        "react-native-watch-connectivity",
        {
          "name": "watch",
          "bundleId": "com.expo.watch.example",
          "displayName": "EAS WATCH",
          "sourceDir": "watch",
          "deploymentTarget": "7.0"
        }
      ]
    ],
  1. If you're already don't have a watch folder with your watch files, create one, you could use mine from here. Please be aware that this is not working with nested folders. e.g. watch/configuration/debug-settings.xcconfig wil not be resolved. (improvement for the future). Also it's important that you'll have a Info.plist there, I need it as a link step
  2. run npx expo prebuild -p ios --clean This will generate native files for iOS including watch target
  3. close xcode if you have it opened and run rm -rf ~/Library/Developer/Xcode/DerivedData/ to delete all cache you can have.
  4. Open newly generated project in xcode
  5. clean build folder of xcode. You can use Command + Shift + K or Menu Bar → Product → Clean
  6. Select watch target and build it for a watch
  7. If possible, use real device because watch connectivity is very bad on simulator, and some functions are not working. It's also on their documentation like here
  8. Select iOS target and build it for iOS device (I'm not sure if expo is starting a metro from xcode, maybe start it from terminal before this step)
  9. test connectivity
  10. ???
  11. Profit Ping me if you still have some questions or issues P.S I don't know how EAS is working (I didn't used expo for years), but from a quick look I don't think this plugin thing will work in EAS. But I can be wrong
yolpsoftware commented 8 months ago

@CristiCeban thanks for the detailed instructions!

(edited: I was able to solve the following problem:)

On step 16 I get the following error:

image

This is my plugin config:

      [
        "react-native-watch-connectivity",
        {
          "name": "watch",
          "bundleId": "ch.yolp.[...].watch",
          "displayName": "EAS WATCH",
          "sourceDir": "watch",
          "deploymentTarget": "7.0"
        }
      ],

I changed it to

          "bundleId": "ch.yolp.[...]",

and started again at step 10, which resolved the problem.

So I was able to build it for the Simulator (on which it said there is no Watch paired). As soon as I have a debugging device available, I'm gonna try it on that, but I'm a step closer.

CristiCeban commented 8 months ago

@yolpsoftware Yes, bundleId is basically the bundle id of a iPhone app (which is the iOS app in this case) I need it for the WKCompanionAppBundleIdentifier info.plist key. You could test for the simulator, but TransferUserInfo won't work, only TransferMessage (so the watch app and iOS should be active at the same time). It's a complete ritual to run both the watch and the iPhone app at the same time (and sometimes it doesn't work until wipe out...). Essentially, you need to pair a watch with an iPhone device using xcode (in the Devices tab) Run the first watch app from xcode (this will start the watch and iPhone) and they should be paired, you can check in this photo, it should be green. if it's not green, force close them both and try again, this is an xcode error (due to Apple).

Screenshot 2024-03-08 at 19 16 34

When it is green, on your iPhone go to the "watch" app and you will see a sync screen, wait for it to finish (might take a while, but if it's taking more than 5 minutes, ignore it and try to do a build). In the meantime, you could now start the second build for iPhone (watch was the first). Don't interrupt the previous build/debugger attached, just change the target to the iOS target name and start the build (and maybe metro in the meantime). If everything is OK you should test connectivity

P.S your watch bundle id will be now bundleIdentifier.watchkitapp (Maybe improvement for the future??? )

yolpsoftware commented 8 months ago

@CristiCeban thanks again for all your work. I was now able to fully build the app in Xcode. However, due to the usual connection problems between my test device and Xcode, I wasn't able to test the app despite trying for several hours (Xcode always complains about "Transport error", see for example https://stackoverflow.com/questions/64974291/xcode-error-failed-to-prepare-device-for-development).

So I tried to instead build it for Testflight, so I could test it that way. This worked insofar as I was able to create an archive of the project in Xcode. When submitting this archive to Testflight, I ran into the following error:

Missing Icons. No icons found for watch application '[...].app/Watch/watch.app'. Make sure that its Info.plist file includes entries for CFBundleIconFiles.

I then went to the App Icons (Watch target --> General --> App Icons), clicked on the arrow and added an icon for the watch target. But this didn't help, same error.

So I opened the archive that Xcode just built and looked at the Info.plist of the watch app. Seems that this file gets generated somewhere. It does not change anything if I add an icon to the .plist file that is in the /watch source folder.

Any idea? Did you manage to build this for Testflight?

CristiCeban commented 8 months ago

@yolpsoftware Hey, sorry for the long reply At this stage, the watch app icon is generated from the watch folder, [mainly] (https://github.com/CristiCeban/watch-example/tree/main/watch) an Assets.xcassets which is linked in the build phase. Could you try again with this folder that mimics exactly the same content? Mainly, you need to make sure you have a folder AppIcon.appiconset. Add the watchos icon here (important - size ->1024x1024 or the build will fail). Also, if it's a different filename, change it to content here as well.

About the generated .plist file, yes, that's right, it mainly consists of 2 things, the .plist file generated from the merge operation between the .plist file in the watch folder and some builds settings If you want to add something, you can go to xcode, select watch target -> info -> add info.plist key. But I think you can skip this if you do the first step described above

Screenshot 2024-03-11 at 18 50 50

Did you manage to build this for Testflight?

We have a couple of app in production with generated watch target using almost the same code like the one from my pr (but not in expo content, we have something custom for injecting it, so without any expo stuff in there). They are used by a couple of millions of user and seems to work fine.

yolpsoftware commented 8 months ago

@CristiCeban sorry for not seeing this! Maybe this would be a helpful warning in the library, for everyone who is as dumb as me. When the /watch folder gets copied to /ios/watch, we could generate a warning if there's no asset.

But now it worked! I was able to submit the app to Testflight, and everything worked fine! So I'm happy to give my OK for the PR.

Thanks again for your work!!

Looking forward to testing it with EAS.

mlabenski commented 8 months ago

Hi all, i've been following this thread and appreciate the level of detail your comments are. I'll follow these instructions to learn how this can be added to my expo app.

CristiCeban commented 5 months ago

I see that more people want to use and test this integration. The author of this package I don't know if he still maintains it, can do release, etc. For this reason I made a fork and published the package as react-native-watch-connectivity-expo. You can download it from npm and use it like any other project. You can look here for an example of the integration. When this pr is merged and a new release is made, then you can use the original version again. Until then you can use the forked version.

CC: @JeffOtano @walterholohan @mlabenski

P.S @yolpsoftware I'll try to look at the subfolder thing in the next little while, as I find the time. I can't give a timeline, but hopefully soon.