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

Make changes required to support Expo config plugin #101

Open
valtyr opened this issue Aug 8, 2022 · 22 comments
Open

Make changes required to support Expo config plugin #101

valtyr opened this issue Aug 8, 2022 · 22 comments

Comments

@valtyr
Copy link

valtyr commented Aug 8, 2022

I'm looking at integrating react-native-carplay into an EAS-powered Expo app. For some background, Expo started supporting custom native code for managed projects recently, and the mechanism that allows this to work is something called an Expo Config Plugin. That should theoretically allow this plugin to be used in custom Expo dev clients (which is very exciting).

The setup

Here's a link to a plugin file I've created which performs all the modifications specified by the readme:
https://gist.github.com/valtyr/48eca6a1b5e3d54d865e2352a6127b6a

This file is transpiled into js and referenced in the app.json config:

{
  "expo": {
    // ...
    "plugins": ["./plugins/carplay.js"]
  }
}

Here's my eas.json file for good measure (notice the simulator: true flag, this is convenient for testing on apps that haven't yet been granted the CarPlay capability):

{
  "cli": {
    "version": ">= 0.57.0"
  },
  "build": {
    "simulator": {
      "ios": {
        "developmentClient": true,
        "simulator": true
      }
    },
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  },
  "submit": {
    "production": {}
  }
}

I then run a build using this command:

eas build --local --platform=ios --profile=simulator

The build command then spits out details about the working directory near the top which lets us inspect the source files and make sure the correct modifications have been made:

[SETUP_WORKINGDIR] Preparing workingdir [PATH_HERE]

The changes

Expo's app delegate file is a bit different to vanilla React Native app delegate files:

- @interface AppDelegate : UIResponder <UIApplicationDelegate, CPApplicationDelegate>
+ @interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate, CPApplicationDelegate>

The issue

The build goes fine until it starts compiling the RNCPStore.h header file. It seems that the client is being built in an ObjectiveC++ environment instead of just ObjectiveC (this is my uneducated assumption) so the keyword template is reserved. Here's the error it spits out:

❌  (ios/Pods/Headers/Public/react-native-carplay/RNCPStore.h:14:71)

  12 | + (id)sharedManager;
  13 | - (CPTemplate*) findTemplateById: (NSString*)templateId;
> 14 | - (NSString*) setTemplate:(NSString*)templateId template:(CPTemplate*)template;
     |                                                                       ^ expected identifier; 'template' is a keyword in Objective-C++
  15 | - (CPTrip*) findTripById: (NSString*)tripId;
  16 | - (NSString*) setTrip:(NSString*)tripId trip:(CPTrip*)trip;
  17 | - (CPNavigationSession*) findNavigationSessionById:(NSString*)navigationSessionId;

My hunch is that this would all work, if another variable name was used.

It would be awesome if a maintainer could help me get this working. I would of course contribute my expo-config-plugin to the codebase. I think react-native-carplay and Expo could be an absolutely killer combo!

@valtyr valtyr changed the title Add Expo config plugin Make changes required to support Expo config plugin Aug 8, 2022
@valtyr
Copy link
Author

valtyr commented Aug 9, 2022

Update

I cloned the project into a monorepo alongside a demo expo app and swapped out the react-native-carplay dependency from npm for my local version. By renaming all variables and method parameters previously called template in the Objective C source code I've managed to get the app to build through eas build. It seems like everything is working. At least I'm able to call the native methods from JS without anything crashing. The only problem I seem to have now is that the app doesn't appear on the simulator's CarPlay screen. My instinct is that the reason it doesn't work is simply that I don't have the CarPlay entitlement yet. This is confirmed by the documentation:

Simulator can’t display your CarPlay-enabled app unless it has the necessary entitlements.

This contradicts what is stated in this repo's readme. Could it be that this has changed since the package was authored? Or do I still have a ways to go with my integration?

Here's a link to my demo repo if anyone's interested:

https://github.com/valtyr/expo-carplay-demo/tree/main/apps/carplay-test

@AlexanderCollins
Copy link

AlexanderCollins commented Sep 30, 2022

@valtyr did you make any progress on this? I'm looking to do the same!

@forki
Copy link

forki commented Nov 9, 2022

I'm also very interested in this

@birkir
Copy link
Owner

birkir commented May 25, 2023

The template variable name has been resolved, so older configuration should work.

But there is no way this is going to work going forward, unless Expo starts supporting custom AppScenes, we will see.

@angeloreale
Copy link

angeloreale commented Sep 10, 2023

I don't see any references to AppScenes in Expo code.

I understand the basic idea behind UI Application Delegate (being able to control a mobile app from the car screen running CarPlay), even though I'm not an iOS developer by definition.

I'm trying to understand whether this is a feature that we can request / contribute to Expo, as I'm also interested in it, but not being a subject matter expert, I would like to gather some requirements before opening a feature request / RFC with them.

What would it take to interface this library usage of AppScenes to Expo build/runtime environment?

When you say custom, is there a default implementation of this feature in their framework? Would it require tweaking or actual enablement?

Thank you,

Angelo.

@birkir
Copy link
Owner

birkir commented Sep 11, 2023

Expo has a custom app delegate called EXAppDelegateWrapper and that is the main entry point of their framework.

So, switching to AppScene is a hefty rewrite of how the Expo framework is initiated. So to put it into words:

It's not about "supporting" app scenes in Expo, its about switching technology altogether, and you will lose legacy appdelegate support by doing so.

@caustin24345
Copy link

caustin24345 commented Sep 13, 2023

Would it be possible to get this working by injecting UIApplicationSceneManifest and all necessary children into the info.plist. This would allow for multiple scenes in the iOS application.

From testing, this is able to build successfully - however the ExAppDelegateWrapper is unable to find the key window once the application finishes launching. If its possible to get this delegate to find the application key window, I believe the scene delegate will connect to the session as well - apparently this was possible in Expo versions < 48.

Car play delegate functions can be set up in the same scene delegate file as an extension. Expo is already looking to fix the issue of not being able to find the key window and can be tracked on this thread: expo/expo#23536

@GeorgeBellTMH
Copy link

Looks like that issue has been resolved...someone could give this a try now...

@janwiebe-jump
Copy link
Contributor

@caustin24345 Have you made any progress? Can you share your code that builds? Thanks!

@caustin24345
Copy link

@janwiebe-jump I believe expo has addressed this issue. A PR was merged to their main branch on 22nd Sept with the fix I mentioned to allow for multiple scenes - expo/expo#24565.

Im not sure how often expo releases, but you could always test pointing your expo version to the main branch to see if you can get CarPlay up and running. My guess is that this will be officially supported by expo for bare and managed workflows in their next release.

@janwiebe-jump
Copy link
Contributor

Tnanks @caustin24345 I got the new expo-dev-client version, and the error has been fixed.

However, the carplay app crashes on launch.
Application does not implement CarPlay template application lifecycle methods in its scene delegate.

I don't have a scene delegate, I am using the updated AppDelegate of this issue.

I've also tried to change the method declarations to this:

- (void)application:(UIApplication *)application didConnectCarInterfaceController:(CPInterfaceController *)interfaceController to:(CPWindow *)window {
    [RNCarPlay connectWithInterfaceController:interfaceController window:window];
  }
  
  - (void)application:(nonnull UIApplication *)application didDisconnectCarInterfaceController:(nonnull CPInterfaceController *)interfaceController from:(nonnull CPWindow *)window {
    [RNCarPlay disconnect];
  }

Since that seems to match the protocol

@KestasVenslauskas
Copy link

@janwiebe-jump Were you able to fix this?

@janwiebe-jump
Copy link
Contributor

Actually yes. I have created my own expo plugin, to use with react-native-carplay.
I also incorporated the proposal of #158 to be able to boot the CarPlay app without having the phone app running.

I don't have the time right now to create a github repo, but here are my files: carplay.zip
I added a plugins\carplay folder and put the files in there.
Added the withCarPlay plugin to my app.json.

Be sure to set the correct entitlements as well. The config plugin adds the carplay-audio entitlement.

@thomas-rx
Copy link

I also incorporated the proposal of #158 to be able to boo

Thanks for your work. Is the CarPlay app (without phone app launched) working for you ?

@nzhenry
Copy link

nzhenry commented Feb 28, 2024

@janwiebe-jump Thanks for sharing that zip file. I have added the contents to a plugins/carplay directory, added the entry "./plugins/carplay/withCarPlay" to the plugins array in app.config.ts, and set the correct entitlements, but when I run expo run:ios I get this error:

PluginError: Failed to resolve plugin for module "./plugins/carplay/withCarPlay" relative to "{project_root}/ios/Pods/../.."

Is there anything else I need to do? Is there a missing compile step for the plugin or something?

@janwiebe-jump
Copy link
Contributor

@nzhenry I haven't tried expo run:ios.
I use the eas cli, with the --local option. does that work for you?

@forki
Copy link

forki commented Feb 28, 2024 via email

@markmccoid
Copy link

I'm having trouble getting the withCarPlay.ts working as a plugin.

I put it in a separate directory in the root of my project ./plugins/carplay and then in app.config.json I've added:

export default {
  plugins: ["./plugins/carplay/withCarPlay.ts"],
};

I get back an error "CommandError: Cannot use import statement outside a module".

I've been trying to find some straight forward docs on the plugins within expo, but they are a bit over my head at this point.

Has anyone gotten this to work properly and could share their steps?

Thanks,

@janwiebe-jump
Copy link
Contributor

@markmccoid I use the Ignite boilerplate and its app.config.ts makes it possible to use typescript.
I import the carplay plugin in app.config.ts like this:

plugins: [
require("./plugins/carplay/withCarPlay").withCarPlay,
]

@tommynordli
Copy link

Actually yes. I have created my own expo plugin, to use with react-native-carplay. I also incorporated the proposal of #158 to be able to boot the CarPlay app without having the phone app running.

Thanks @janwiebe-jump, this was really helpful! I managed to get it working. However, after upgrading to Expo v51, I get errors in my AppDelegate on createBridgeWithDelegate and createRootViewWithBridge as they're no longer available on the EXReactDelegateWrapper.

Has anyone managed to get this working on the latest expo?

Screenshot 2024-05-22 at 14 27 46

@janwiebe-jump
Copy link
Contributor

@tommynordli I see the same. It looks like bridgeless support has been introduced in Expo PR 27601, and support for the bridge has been removed.

I did not find a solution yet. Maybe @DanielKuhn has ideas, because config plugin was based on his work as well.

@DanielKuhn
Copy link
Contributor

Sorry, I'm not using expo... But it looks like you need to adjust your AppDelegate code to the new Expo EXAppDelegateWrapper-code - just like I need to adjust mine to the new RCTAppDelegate-code on every react native upgrade.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests