Jon (00:21.41) You're listening to Gone Mobile, your input and output for all things.NET, mobile, and Maui. Jon (00:39.402) Welcome back to another gonmobile. I'm here again once more with alan alan. How you doing today? I'm not too bad. Um today though, you know, we've got a topic that I hate to say We were bound To cover sooner or later Yeah, yeah in case you haven't figured it out I did actually No, I haven't. I don't know if i've used it on anyone actually. It's it might be my new favorite one. So Allan Ritchie (00:44.422) Good. How are you, John? Allan Ritchie (00:57.422) You've been saving that one for a while, haven't you? You had that prepped before we talked. You haven't used that on me yet. You had that planned. Allan Ritchie (01:08.338) That's pretty rough. All right. Jon (01:09.994) If you're listening and you're not sure what's going on yet, today we're talking about bindings. So what are, Alan, what is your understanding of what bindings are in a mobile.net, Maui world? Allan Ritchie (01:23.226) That's where we take the native libraries and try and make them work in our dotnet world. That is the simplest layman's terms. I think. Jon (01:30.434) That's very concise. So one of the interesting things that happened when we moved over to Microsoft was, bindings was a term that nobody seemed to really understand. We were using it always at Xamarin, it's bindings. Yeah, of course. So Microsoft, the term often that you might hear that's similar to bindings is the projection of APIs, of native APIs into the managed.net world. So if you've heard... Allan Ritchie (01:59.07) Doesn't it interrupt? Jon (02:00.466) Yeah, interop and specifically I think it came from like the WinRT, the Windows stuff where they had the Windows APIs and those were all C++. And then they had projections of those into C sharp and projections of those into JavaScript too, I believe, if I remember my history. It was a thing for awhile, but this is, this is not an uncommon topic no matter what area of, of development you're into, right? At some point you probably want to try and get to use from the language that you're writing code in to use some other library or API or call that is in a different language or a different area. And so how do you make those things work together? So today, that's what we're going to talk about. Now, bindings are, very near and dear to my heart. Uh, if I, you know, in the Xamarin days was first joining on as part of the components team and the components team, we made a bunch of bindings to just all sorts of third-party libraries. The idea was, you know, back then also in the space, you couldn't do as much with your apps with a lot of the, in the box or, or like APIs from Google or Apple. And so a lot of people made different libraries. Remember before we had like pulled a refresh as a real thing, there was some app on iOS that invented this idea. Basically they had put out a library in an objective C and we made a bind into that library because this was cool. We want to have pulled a refresh in our apps. And of course that kind of became an in the box thing. And that sort of highlights the story of, of where we are a little bit more today. I think, um, we don't have as many. libraries and stuff that we're trying to pull in. I feel like in apps that I'm seeing anymore, there's definitely still some. And so there's a need there, but it's not as prominent. Like I don't think we see as many apps that just have all sorts of different bindings for various reasons anymore. Allan Ritchie (03:57.878) No, they've pretty much disappeared. I think the only bindings I find I'm doing these days are still Android, because they keep moving the needle. It's always Android. Jon (04:06.902) Well, an Android has done the interesting thing of moving a lot of their core platform stuff out into these Android X libraries, these play services, libraries, these Firebase libraries. And to the point where I use, I like to use GPS as an example, because there are APIs in Android, like Android dot jars, kind of like the core set of Android APIs, right? And there's geo location type stuff in there. But then Google basically said, you know what, anything that we're gonna like really improve upon, we're gonna put in our Google Play services library. And so if you wanna get like the access to the best version of some of these things now, you need to use those libraries. Now, fortunately, we do still bind and maintain bindings for a lot of those core libraries, but that's not always the case either, right? I mean, what's your experience in dealing with bindings? You know, what are you looking at today with them versus I guess like, years ago in Xamarin. Allan Ritchie (05:02.107) I think... The funny thing is, it's always those Android X libraries, right? Like the funny thing is, so I think we were talking about the Health Connect the other night. I always try and bribe John to do these or look at them for me because he's the grand master of the bindings. But there's such a pain sometimes because obviously Microsoft doesn't want to take any of the alpha or the beta ones, which I understand. And some of the Android X libraries, it's seemingly stay in alpha and beta indefinitely. So the health connect, for example, is listed as an alpha and they just released Android health to the world. And it's like, OK, well, is this alpha or like how are we working with this right now? So that's one of the cool. That's one of the I don't want to say cool things, but difficult things. Jon (05:32.994) Yeah. Allan Ritchie (05:51.622) Um, but they're basically moving everything to Android X. So eventually everything that's not public API facing is going to be on these Android X, right? So it's coming at us like Bluetooth. I think I found that the other day was an Android X Bluetooth. And I was like, what the heck is that? Are we, are they doing this? Jon (06:01.003) Yeah. Jon (06:07.626) Yeah, the sprawl of them is quite large. And I remember still being on the components team and leading the components team for a while too. Just having to deal with these things like multiplying, Android just kept growing and growing and growing. And all of their libraries were like interdependent on other Android X libraries and stuff. And so the dependency chain was very complex too. And that made it even more challenging for a number of reasons. Allan Ritchie (06:32.41) I think it's gotten worse too, I don't think it's gotten better. Jon (06:34.162) Yeah, I don't think it has gotten better either. But before we dive too much into that, I think it would be helpful, especially for those who are newer in the Maui ecosystem, to understand a little bit more about what bindings are, how do we make them, how do we go about this, how do they differ between the two platforms? So we talked a little bit about Android. So let's maybe start there. Do you wanna walk people through what you do when you go and create an Android binding? Allan Ritchie (07:03.434) Oh, that's a, that's a fun one. Um, that's a fun one. It kind of depends, right? Like how big of the surface do I need to take in? So I'll go back. The health connect is fresh, right? I'm just started getting that to work. Um, so John, for what you don't know, he has all these little tools out there. He has the, what do you call it? The Xamarin binding helpers. Is that the. Jon (07:15.063) Yeah. Jon (07:25.694) Yeah, yeah, there's a library for that or there's a repo that has some stuff in there. Yeah. Allan Ritchie (07:30.266) So that takes an Android Studio project. So I could do kind of the normal dev. I can bring in libraries and do what's called the slim binding, basically create a class that does what I want it to do in Java. So instead of kind of emitting the entire binding, it's just giving me the subset of what I want that I need to work with. That's kind of a cool little thing because it deals with all the downstream dependencies, mostly, mostly. Jon (07:55.902) And like the default is not that obviously, right? And when you're creating a binding project, like if you go and say, I have this library, I wanna bind it, maybe I have all of the jars or AAR files, which are like the native platform typo file that these things are contained in. You, like the Android binding side of things. Um, I'm assuming that you've had, that you've had lots of fun writing, you know, XPath statements and stuff. So like the project type is, uh, the way that it works is you have this XML file. By default, we try to bind everything in the library, right? So like every single public facing API and stuff is, it's going to go pick up the, the binding generator is going to say, yup, I see this. I'm, this is how I think it should be bound and come out. And then obviously that's never. perfect, it never seems to work 100% and there's fix ups. Right, so I don't know if you found, one thing I seem to always find over the years is Java libraries or Kotlin libraries, because Kotlin compiles down to bytecode, right? So when we're talking about these things, we're kind of talking about both for Android. And those libraries often tend to be written. Allan Ritchie (08:48.582) You get a ton of errors when you do that. Yeah. Jon (09:08.094) In a way that's really, um, like inheritance heavy, like there's just long chains of things, subclassing other things. And that kind of makes things more challenging because then when you pull in, uh, an API and the binding generator is looking at it and saying, Oh, I, this, this method returns this type. Well, this type is actually subclassing this type and that subclasses this, this other type. And, and so you quickly kind of get to the point where we start with these. you know, the binding generators, yeah, I can, I can talk binding generator saying, I want to bind this whole surface and then you have all these errors. And so that the technique is like, you have to write these X path statements and stuff to sort of either change the things that it didn't interpret correctly, which is probably the hardest case, or to say like, you know what? I don't care about this, this type. I don't care about this method that returns or takes this type as a parameter. Allan Ritchie (09:54.91) for sure. Jon (10:02.386) I just want to remove it from the binding so that it's not causing me grief. And so that was kind of the, the juggalo is right of like, how do I remove the stuff to kind of get rid of the errors, but then keep enough of it or change enough of it that still gives me the C sharp projections or bindings to those APIs that, that I need to use in my app. Allan Ritchie (10:22.082) And that can be challenging to write sometimes for sure because I call it there's a little bit of a black magic in terms of, you know, you could just put in two X path statements and fix the entire, like you could get like 200 builders and it required to X path statements and it fixed the entire library. But it's like there's a bit of a bit of an art form to it to figure out what that is. And sometimes I've been lucky enough and I've been like, oh man, I hit it. And sometimes it's been like Jon (10:35.303) Right. Allan Ritchie (10:51.619) a churn, right? Jon (10:53.202) And, or like the ones where you, you fix like one of them, but then it causes like six others because the thing you fixed, you know, now is broken on those other areas. Allan Ritchie (11:01.95) Right. There was a set of libraries I did for Adobe. I think this was about a year ago. And I think I was talking to John quite a bit about this and it had such a dependency and a chain going on. Like there was, I think by the time I was said and done it was 22 libraries or something. And that binding, that took a few days of effort and I still don't think the customer ever figured out what they really needed out of it. So Jon (11:20.939) Yeah. Jon (11:30.654) And it's worth noting too that like these binding tools are essentially what the Android and iOS teams themselves use to actually create the bindings for the core platform APIs. So like I mentioned Android.jar, that's like where Google has all of like the core platform stuff, right? And so we use the tools against that. There's some other kind of more deep aspects to it that they use to like turn enums into Allan Ritchie (11:31.314) fun. Jon (11:57.91) better C sharp representations of the enums, or make things kind of nicer, which we don't always do, I think, if we're making the binding ourselves, because we just want to be able to use it. Allan Ritchie (12:09.682) The platform APIs are usually cleaner though to bind, right? Because they're almost purest, right? Whereas Android X is trying to version, make your entire platform version agnostic for Android. So you end up with like, you know, here's your fallback APIs and here's your, you know, built on top of native or the platform stuff. So it's cleaner, it's easy. I don't wanna say it's easier. I'm not trying to take away from the team, but certainly. Jon (12:13.843) Yeah. Jon (12:33.382) No, and I think there's less churn there nowadays too, right? Because they're pushing more stuff out to the Android X libraries, there isn't as much that changes in the core from release to release. So it's a little bit more stable at this point. Allan Ritchie (12:46.162) Knock on wood. Jon (12:47.178) Yeah. So that's the Android kind of side of things, right? I guess the other thing that I was gonna mention too with Android that makes it more challenging that I found over the years is that Java, either developers or the rules around Java, I mean, first of all, they don't line up one-to-one with C-sharp. So there's inherently always a challenge of trying to do this where you're trying to expose concepts from another language, essentially, right? In this case, it's like bytecode concepts and make them make sense to map to a C-sharp concept. Luckily, Java is pretty similar. So it's not crazy, but they have some different rules around the visibility of members and stuff. And I know I've encountered enough cases in the past where Google would have something marked, I think, as like private or internal, but you kind of needed it because some other type references it. And it's just this kind of messy, like, oh, this doesn't happen in C-sharp because... that doesn't really let you do this bad thing. So that kind of stuff is always a challenge. Allan Ritchie (13:51.29) I feel like that was the segue to iOS. I thought that's where you were going with this. Okay. Jon (13:54.406) Why it is we're getting there. Yeah. So iOS is a little, well, quite a bit different. Now I always kind of think of, I always think like iOS and Android are almost opposite in how they approach it because Android is we want to try and generate everything and you tell us what to remove or what to change. And iOS is like, we don't, we'll generate whatever you want us to do, but you have to write those things in and tell it. Allan Ritchie (14:01.362) It's a far different beast. Jon (14:22.206) hey, I want this method of this type, I want this other method. Now there is a tool that has been used over the years called Objective Sharpie. It's still, I think out there, you can still use it. And it tries to do its best job of essentially generating like pseudo C sharp code, right? So a binding for iOS is a weirder thing in the sense that you have kind of these steps. The intermediate step is to write some, what looks like C sharp code mostly. to describe the Objective-C API in such a way that then the iOS binding generator takes that information and actually does a bunch more generation of code to make all of the glue between those things. But to do that yourself and write the final code is just really hairy and you don't want to do that. So we have that intermediate step that makes it a lot easier. However, You know, it's not perfect. So objective Sharpie will look at like header files and, and because of the nature of, you know, C header files, it's really not that easy to parse out. So there's not, you know, this kind of foolproof way to say, like, given this header, we know exactly what to do. And then objective C adds kind of another layer of that because there's the way that they, they name selectors and stuff doesn't really map cleanly to C sharp method names and things. And so sometimes we'll do some what we think is the right idea to do, but you'll have to go fix up the naming because you're like, oh no, that's really weird and doesn't make sense to me. And they do that a lot in the core iOS APIs and those core frameworks. So that's objective C, first of all, yeah. Allan Ritchie (16:05.262) Yeah, we haven't. You notice he's saying Objective-C and not Swift because that's another issue. But one of the other things too that I usually find with the Xcode libraries and stuff is you have to find the right framework and then you have to go through all the compiler settings. And I think this is where a lot of the.NET devs tend to break down is they don't. They don't like even sometimes I'm like, oh, it's called an XC framework now or it's what it used to be. Jon (16:18.304) Yeah. Jon (16:32.51) Yeah, well, and Apple has changed this a lot. There was just normal dot frameworks, right? Like it was a framework. And the framework was kind of like a bundle with the static libraries or dynamic libraries, I guess, and header files and stuff. Yep, so we can talk about that too. And then they've started making, they made XC frameworks. Is that the final iteration? I might be losing a step, because what we have now is basically a framework Allan Ritchie (16:35.523) Yeah, two times. Allan Ritchie (16:39.856) Yeah. Allan Ritchie (16:47.266) Yep, which is another big difference. Allan Ritchie (16:59.23) pretty sure it is. Jon (17:02.242) that can bundle all of the different builds for different architectures in it, right? So you've got iOS, but on iOS, you have simulator versus device, and you have X64 or ARM64 for both of those now, and you used to have X86 for simulator as well on iOS. Maybe we even, was there ever devices that were X86? Maybe one of the Apple TVs? I don't know. I don't think so. Yeah. Yeah, so, you know. Allan Ritchie (17:06.436) Co- Yeah. Allan Ritchie (17:24.702) I don't think so. No, that doesn't sound like Apple. They want everything on ARM. Jon (17:30.754) But that keeps changing. And I think with XC frameworks, there's maybe a little bit more information to describe like things that you would need to link in and stuff. But yeah, you're right. You would have to figure out what are the right linker flags to use? What are, there's other settings and stuff. How do I know which dependencies to pull in? And yeah, like you said, frameworks to pull in. There's always like this, it's an objective C library or it's a C++ library. You know, you had to know how to do that. Lots of little things, yeah. Allan Ritchie (17:59.73) That's a fun one. We tried to do that with SQLite and I think some GPS stuff that we were working on. Jon (18:06.278) Yeah, it's not easy to understand by far, but that's objective C and now Swift is a little bit different again. Right now today, there isn't really a way that you can easily interrupt Swift directly from.NET app. That is something that's being worked on and I think I can say that because there's GitHub issues out in repos that are describing some of the effort going into that. So that's, well, so that's one, yeah. Allan Ritchie (18:29.647) Right now you have to do the slim binding. Jon (18:33.926) You can, a lot of Swift frameworks out there, or Swift libraries will also include the option to generate Objective-C headers to interrupt with. And so when you, and this is like the whole slim binding concept that we'll dig into a bit more. Same idea as you would enable the Objective-C header generation, and you're actually binding to the Objective-C headers in this case, not the Swift directly, but it's nicer to write on the... Swift side in Swift, I feel like Objective-C was always like the worst. My favorite example was always strain by concatenating string was like the method call that you would use to concatenate two strings together. And that just always felt like horribly ugly to me. Allan Ritchie (19:16.474) Well, yeah, you're not wrong. It is. It is pretty, I don't know. Objective C was a kind of a weird language. I mean, it's good to, you know, on Objective C, you can err on its Swift libraries when they include the headers. But I think that's becoming less and less now because everybody's writing in Swift. So it makes it harder and harder. Jon (19:33.642) Yeah, there's definitely less. I think there's still a fair bit of it around. But yeah, that maybe is a good segue into, I think we covered the basics of what these iOS bindings and Android bindings are, right? There's documentation you can go read to actually do them, but that's kind of the general process. So right now, like we said, that's kind of hard to do. You have to have specialized knowledge of both. how to get these libraries for one, which is still a hard thing even with some of these other techniques that we'll be talking about. Like Android, the one I like to use, the example I use is Mapbox. If you've ever tried to use that library or bind that library, just even getting the dependency set, kind of like you described with HealthKit, it's almost another level up challenge because with Mapbox, they have their own custom Maven repository. that requires authentication. And so the easiest way is really to use an Android Studio project to go and download those things for you and for you to understand where it puts those that you can go get them and copy and paste them over. Because like the guide, if you go to Mapbox's documentation is like put this key in this environment file, you know, profile file and add this Maven repo to your project. And then you add the... the Maven artifact information, and then it'll all get added to your project. But as a.NET developer, it's like, well, how do I even, how do I get that? I can't just download it. So that's a challenge. And this is why I start to kind of like the idea as we talk about improving how we bind things in the future of leaning more into the native platform side of things. Like let that part be the thing that guides you through that basic setup. So. Allan Ritchie (21:05.734) Yeah, you gotta go through some steps. Jon (21:25.918) Most of the libraries you're gonna use are gonna have like a guide, right? Here's how you add it, here's a basic hello world kind of example of it. I can stumble through that as a developer, even if it's in Swift or Kotlin or Java, like I can follow a guide. And then if I can get to that point and write a little bit more code, you know, that doesn't seem so bad. So slim bindings, I don't know who, I don't know if I coined the term when we were talking about it internally or somebody else did, but. The idea being instead of trying to bind the whole API surface of a library so that you can use it in C Sharp. One, because creating bindings is hard. You have to kind of learn a new skill completely. And I might not always need every API from a library. So the idea with some bindings is, well, let me just create my own abstraction or my own like interface, my own part, way to interact with that native library. Allan Ritchie (21:57.25) Expose what you need. Jon (22:23.646) and I'll do it in Java or Kotlin and I'll do it in Swift or Objective-C. And the API that I build, that I expose, if I do it in such a way that it's only exposing really simple types, I'm not doing any crazy subclassing all over the place, which a little bit is fine, but I'm not doing anything too wild. And I try and use basic types, and I try and use types that.NET already knows about. which is one of the advantages I think over some other frameworks and ecosystems is I can create a slim binding that I'll use the example of Mapbox again that returns a map view object from Mapbox because that map view is actually a UI view on iOS. And so if I make my public API say like get map and it returns a UI view. Even though I'm sending back an instance of that Mapbox view from the native side, my app doesn't care that it's a Mapbox view because all I really wanna do is get that view and display it in my page, right? And so that's the idea with slim bindings is that you create that boundary yourself. And when doing so, if you do it in a simple enough way, to do the binding against that API should almost always just work out of the box. Like Objective Sharpie should pretty much nail it for you. And also like the Android binding generator, if it's a simple one, it'll nail it. Like it's fine. It'll, it'll generate something useful for you. And. Allan Ritchie (23:53.382) Well, and that's the thing, if you're bringing out these big APIs, you've just got that much more work to do because you are bringing out everything you're bringing out. Like you said, what that UI view is fully if you want the full measure of what it's going to do. So now you've got like this versus it's kind of like the. You're almost doing the XML right you're whitelisting into what you need versus having to blacklist things right. Jon (24:20.906) Yep, exactly. Yeah, so that's kind of one approach. I mean, that still has the challenge of how do I get the dependency chain? How do I build the library in such a way that I can then consume it from my C-sharp project? And I know you've kind of dipped your toe into this world a little bit with what you're working on. Like how has that been? Do you think it's a useful strategy? Allan Ritchie (24:49.586) I'm still toying around with it a bit. It certainly on the iOS side for sure it helps doing the slim binding because iOS like objectives sharpie. It's not really maintained anymore. I think that you stood there still occasionally appear that goes through for some reason, but it's a bit out of date. So, you know, you end up doing all that stuff yourself. So the less you have to do, the better off you are. And that you can kind of fumble your way through if you expose just enough of that API because you really don't need a ton. Now when we talk about health, unfortunately, there's that health connect from Android. There is a whole lack of types and data you need out of it. So you don't have the luxury of returning like a view that's already bound to dotnet. Like you have to you have to bring all those types to the forefront or you have to simplify them. Jon (25:35.01) Right. Jon (25:40.482) I was gonna like, are they types that you need to like interact with a bunch? Is that an opportunity to try and do something like serialize the data to going back over? Allan Ritchie (25:49.83) So the fun thing is that everything's a query, right? Like you're querying, so for instance, the exercise client, which is like a static variable off of the Health Connect client or whatever it is. So what you have to do is you have to basically say, exercise client, here's one of your base methods. get runs by X dates, right? So the dates are fine. You have that. But then the data it's going to return is usually like some complex object that says, okay, here's your start and end times or your timestamp of when that event happened based on kind of the info you gave us. Here's how fast you might've been running. Here's how many steps you took. Here's how far you went. Like it just, it exposes all of these different properties. And it's usually a fairly rich object. Android loves to do their very rich objects nested deeply. And so you end up having to bring the whole darn thing out, whether you want to or not. Jon (26:44.077) Yeah. Jon (26:51.618) So does that like, when do you feel that there's a line that you cross that decides, okay, this thing is actually something I need to bind the whole library of? Like that would be easier at some point than just trying to create like the, your own API and, and stubs kind of across the wire. Allan Ritchie (27:11.362) I don't have an obvious answer to that question, unfortunately. So this one, I am trying the slim binding. I am trying it with your helper's library. And the reason is, is because of the amount of dependencies of this library tends to pull with it. Um, so the goal was to kind of cut down on that dependency chain as much as possible. Uh, so far that's been helpful. I did get that binding, at least the initial part working. Jon (27:21.643) Yeah. Allan Ritchie (27:36.358) But when I did the actual, you know, the regular binding, there was just a bajillion and a half errors. And it was one of those ones that if I was gonna find those two magic ex-path statements, it was gonna be like two days worth of effort combing through it. So I think the slim binding's been a good route to go on because I have something. I have far from everything, but I'm going places that I need to go now just slowly. Jon (27:47.169) Yeah. Jon (28:04.598) But the thing I also kind of like about it in theory is as the, those native libraries change, like if Google does an update that drastically changes it. If you're doing the full binding, you're kind of sometimes back to square one to redo that binding, right? Whereas if it's the native code that you've kind of wrapped around, often they don't, you know, that might be still different that you have to go and fix up your code, but maybe that's actually as a smaller amount of effort to do then to try and just redo the whole binding again. Allan Ritchie (28:36.046) Yeah, that'll be a curious thing because again, this library that I'm binding is an alpha and it's been alpha for a really long time and it's changed quite a few times. So I, that might end up being the case is they keep changing this. So. Jon (28:41.152) Yeah. Jon (28:50.474) Yeah, the other thing with the slim binding approach that is maybe a little bit more advanced or not obvious, too, that I like is if you're writing your stuff in Android Studio for that side of the world, if you do end up with a lot of complexity on that side because you're trying to hide some of that complexity from going back across, you can actually go and attach your Android Studio debugger. to your Maui app that's running, and you can debug both sides of the world, right? So you can start to, if you really need to get in a case where you're trying to troubleshoot something that's happening over on the native side, like you can totally set it up. It's a little bit of effort to go attach to process and do all that right stuff, but you can hit breakpoints, you can do stuff. It's kind of cool to see that all in action. So I don't know if you've hit that yet. Allan Ritchie (29:34.986) I have. I have never done that. Usually if I'm having a problem with the native library, I'll write a native sample and I'll test it there to go. Oh, what am I doing? Oh, OK. Jon (29:42.199) Right. And that also, like, that's another kind of cool way to approach that too, right? You could have your library, your module that gets bound for the slim binding, but then also write a little app that references it that's native and start to do things with it there too. So that can maybe even expedite some of the process, um, because you're just dealing solely with the stuff there. You're removing a variable from the equation. Allan Ritchie (30:06.85) Right, you're not having to worry about is this my binding or is it something stupid that I've done with the library. And sometimes it can be both. Jon (30:12.973) Yeah. Jon (30:16.242) Yeah, very true, very true. Um, and then in terms of, you know, iOS side of things, have you, have you done any bindings there lately? Allan Ritchie (30:26.838) I've been doing them, like I said, it was this one project again with Adobe and they were shipping their new versions in Swift. So that made it difficult. The funny part was is they had this huge API surface and this huge dependency and chain in the whole project. And I needed like six methods out of it. So Jon (30:51.082) Huh. Allan Ritchie (30:53.478) Basically it had an init and a few calls we needed. So I brought in all the dependency chain there, made the five or six methods we needed and that was my slim binding, turned it all into an XE framework. I know that sounds easy, but it was not. It was still a bit of a pain. Jon (31:09.47) Yeah, no, it is. I, one of the things that's always surprised me that's so hard is like getting the XC framework and all of the architectures and the bundle and everything. Like it seems like that's still not super simple out of the box from Apple. I'm not sure why. Allan Ritchie (31:21.482) No, well and then you have to turn all the, you have to make sure that all the frameworks you're pulling in are also, you know, supporting simulator, which sometimes they don't. And then you have to explain that to your users. Well, there is no simulator for this deal with it. Jon (31:27.681) Right. Jon (31:31.936) And Jon (31:35.602) Yeah, sorry. Nobody, nobody made it for that library. Yeah. I think though it seems, and I think it's still the case that on the iOS side of things, the whole like crazy dependency trees are a little bit less so. Um, so it's sometimes easier to manage or discern, you know, what are the libraries I actually do need to pull in? Like maybe it's a handful as opposed to like 50. Allan Ritchie (31:58.226) And yeah, that's the truth, right? They're usually small and very much more direct in terms of what they're doing. The funny thing is, when I think about it nowadays, I don't have to do a lot of iOS bindings. I'm not sure. I think it's just because Apple builds everything in for the most part and you don't really have to do the bindings. Thankfully, the only one I have and I like to bug John about this one. Jon (32:13.282) Yeah. Allan Ritchie (32:21.454) Is the Firebase libraries. It's funny. It's the Google libraries that we need. For iOS right in our bindings and I think the Xamarin days that you guys carried those over Microsoft still carries them kind of issues. But that's the one we end up needing the bindings for. Jon (32:23.466) Yeah. Jon (32:35.204) A little bit, yeah. Jon (32:40.23) And that's the one I think that I'm hoping a lot of the alternative approaches work better for in the future. Um, there is the bit of the dependency chain that you have to, to reason about, but like, you know, maybe the starting point for that is for somebody to go, you know, I'm not going to say who, uh, but somebody to go. Make the Xcode project template for like how, how to even reference those things and then how to have it, the Xcode project already set up to build properly in such a way that it's easy to include. Allan Ritchie (32:58.77) Hint, hint. Jon (33:09.586) in a Maui project, and then you could go fill in the Swift code for the parts of those different libraries that you actually want to use either with slim bindings or platform channels, which is another concept in the whole thing. Yeah. What? Allan Ritchie (33:22.142) segueing the thing the thing before we go down that path too is that the fun part about the firebase libraries is you need like two things out of it two things Jon (33:34.462) Right. It's like the init method for messaging and for maybe analytics and maybe ads, right? Like there's, yeah, it's very, and this is this, that's actually why the whole concept of slim bindings and platform channels was something that came up or something that I thought a lot about was because we were seeing all these cases where we would bind a Firebase library and somebody will want a bunch of stuff from it. That's, that's fine. Um, but most people were just like, I just want to I just want to register for notifications. Like just, that's all I want to do. Like I need these two methods and it's like, well, why are we maintaining this whole crazy thing that gives us grief every time they update it and all you need is these two things. So platform channels. Allan Ritchie (34:21.546) We'll let, yeah, this is the one that John's been waiting to talk about. Jon (34:24.726) This is, this has been a little bit of like, like I said, I've, I've been involved in bindings for so many years. It's, it's an area that I know is challenging for customers because it was challenging for us too. And I, it's, it's another area that I would love to see us getting better at and making it easier. And I still see people who are running into this in the community who are saying like, I get it, it's workable, but man, this is hard. Like this is, this is above my pay grade, right? And so platform channels is very similar to slim bindings. It's slimmler. And yeah, sorry. I'm not even gonna edit that one out because it's just too good. So it's close to the same concept, except we've kind of gone ahead and defined a contract, an interface, if you will, for the slim binding part for you. So the idea is I get my Xcode project, I... Allan Ritchie (34:59.39) Wow, that's two today. Allan Ritchie (35:04.525) Okay. Jon (35:22.426) Add the Maui platform channels. This doesn't exist yet. This is all theoretical There's a repository will link to that has like the code for doing some of this But I haven't ever taken it to the point of actually like building a cocoa pod Which is like X codes version of new gets or now it's some swift packages or something. There's a bunch of them There's pods too. There's both. There's like three different things It's that's part of the pain of doing this potentially is there's like three different packaging systems now Allan Ritchie (35:41.891) It's still pods. Jon (35:52.106) So you would go install the Maui platform channels, Coco pod into your project. And that would give you this set of APIs for like one to initialize your app because you might need to run code from the Xcode side, right? From the Swift side of things. You might want to start code there. Maybe there's some kind of listener or service that you want to start up from a native binding and or sorry, a native library. Cause it's not a binding at this point. So you've got an init method. You would need to like name that something and know the name because you're gonna have to tell the.NET side of platform channels what that init method is. That init method also would be responsible for wiring up kind of these channel, the platform channels and listeners for these channels that will have messages going across. So the concept really is to create these platform channels between the.NET world and the Swift world in this case. so that you can send messages back and forth from either side at any time, and you can register on either side to receive those messages from one another. So it's a really simple like message passing bridge, which is I think similar to what Flutter is doing. I think it's similar to React Native too. They have kind of like an even more simple, in a sense version of that is my understanding. And when you have that bridge, so like I like to use the Mapbox example always. What I could do there is have my initialize call creates my map. Maybe it adds some pins to the map or maybe it doesn't even. And then my platform channel can send back that map instance over. Again, this is because we have like knowledge of some types like UI view, I can do the same thing there, right? I can say like send back that map over to UI view. And... then I can register a channel that is listening on the Swift side that when the.NET side says, hey, I wanna add a pin to the map, here's the latitude, longitude and color of the pin, right? These are all simple types that we're just sending back and forth, strings and integers and doubles or whatever. So this platform channel interface has knowledge of these basic types that are going across the wire and I send things back and forth. On the Swift side, I add the pin to the map, I add a callback. Jon (38:18.154) in Swift to that pin, so when someone taps that pin, on the Swift side of code, I have a callback that executes. In that callback, I can then say, oh, go send a platform message over this channel, right, to the.NET side that this pin was tapped. Here's the identifier of the pin that was tapped. And on the.NET side, I'm listening for that, and I do whatever I need to do, and I can keep going on my way and passing these things back and forth. So it's really the same as slim bindings in a sense. that we've just predetermined what that API surface is for you and turned it into like this message passing API. Allan Ritchie (38:54.97) You think there's going to be some performance challenges to that? Jon (38:58.414) Um, possibly. Uh, I think the interesting thing is that, I mean, we're, we're going over the Interop boundary for bindings anyway. Right. So, so if you're going to say, add a pin to a map, it still has to cross that boundary. Uh, I think what's interesting is there's not, it's not like a JavaScript or something where you have like one thread that you're pumping stuff back and forth across, like I know that was a challenge, I think even just with react native in general to, to early days. Like I think they've done a lot to accommodate for that. But. Allan Ritchie (39:05.458) Fair. Yep. Jon (39:28.038) Originally, they were hitting bottlenecks, I believe, and somebody will probably angrily tell me I'm wrong. That's okay with that passing back and forth. This doesn't really suffer that because you're not doing it through like one thread or anything. You're still interrupting over the wire into different areas of code. It's just that we've already done that ahead of time. It's ahead of time bindings. Allan Ritchie (39:51.084) Oh yeah, you've just coined a term. Jon (39:52.941) Yeah. Jon (39:56.354) So I think it can be in some cases, like if you take your health kit thing, health, what was it called, health connect, that might be a harder cell to use this because there is some verbosity in just establishing like here, I have different identifiers for what types of messages I'm passing. And this method handles this identifier of a message. And then you've got to like, Allan Ritchie (40:05.266) Health Connect. Jon (40:24.738) construct and deconstruct things going back and forth. So there's more boilerplate may be involved to set up this kind of system, but the advantage being it doesn't require any knowledge of binding at all to do it. Allan Ritchie (40:37.23) Well, how would that work? So let's say I want to bring in an XC framework, right? So I've got an XC framework. How would I go about referencing this? What changes there when I do that? Jon (40:46.846) Yeah, it's a good question. And that part of it is still kind of similar to Slim Bindings. So I don't think we've really answered that really great today. Like you still have to know in my Xcode project, first of all, you've got the, the Slim, sorry, the platform channel kind of library itself, right? Like the top level Xcode library of that project. So you would have to go reference that in your.net project. And to do that, you'd have to add like the, was it the native frameworks, uh, item group item? I don't know if there's still a way to do that even in VS to say like right click and add native framework, there might be here native reference. Okay, so you could do that, but then you'd have to do that for all of any of the dependencies that you are using in that Swift project as well, right? Allan Ritchie (41:22.35) Nah, it still works. Yeah, it's still there. Allan Ritchie (41:31.802) Yeah, that's usually where the challenge lies. Jon (41:34.218) Yeah, so we haven't solved that yet. I'm kind of hopeful that at some point we could figure out a better story there, especially if you scope it to maybe your Xcode project, you use CocoaPods in it. And because there's a pod spec, we could go start looking at that and figure out, oh, here's all of the libraries that you're actually referencing and include them based on that information. If you've got like a one-off native library somewhere, it might be kind of hard. We'll have to be leaning on our iOS, um, you know, gurus, so to speak, like Ralph and, and Alex and Manuel and others and figure out like, do they know. How to get some of that information reliably in like a programmatic way that we could just automatically reference those things for you. I'm not sure. Allan Ritchie (42:20.914) You know, the tooling here would be awesome if you could just pull it in and it was, you know, it could either call out to Xcode to compile or right in Visual Studio, you still had like a Swift editor or something that you could do right there. And the tooling could tell you, yeah, we don't know what the heck this is. What are you giving us? Jon (42:25.671) Yeah. Jon (42:36.354) That is. Jon (42:41.071) Yeah. I think it's actually in the Platforms Channel repository that I have. Someone had helped, who was on the iOS team at the time, contribute some work there. And there is a mechanism to do some like super basic interop with Swift directly, I think. And they started looking at using that as the way to, cause like there is almost a... dynamic binding that still has to happen with platform channels for that first init call. So in my Swift library, I have a class and I have a method in there. And I have to tell the.NET side of things that here's the class and method name that I want you to call when you initialize everything, right? So it's dynamic in the sense that we don't know that ahead of time unless we were to enforce the actual class name and everything, which maybe we should do. But I think he had some... code that was calling into that Swift directly that didn't even need the objective C, uh, header interop. So I'd have to go look at that again. Um, so it's, it's totally possible to, to do, I think a lot of parts of this. It's just a matter of, yeah, sitting down and, and building some of the tooling around it, uh, you mentioned the, the Xamarin binding helpers that I had made a while back, that was a experiment. That tried to do that for Android studio, right? Where you can actually add an Android. Project. Allan Ritchie (43:41.66) Interesting. Jon (44:04.718) uh, into it's like an item group, I think into your, um, dotnet project, your, your Android Maui project, and it'll go out and I think it invoked, does it invoke the cradle? I can't even remember now. Yeah. Right. So it'll go try and build the project for you. You tell it like the module name of the Android studio project and it'll go pick that out and it's supposed to go try and reference all of the dependencies and everything for you. Um, Allan Ritchie (44:17.178) Yes it does. That's where I was having the build issues. And we got that solved. Jon (44:32.498) It gets tricky when you get into the area of like Android X stuff or things that you might have in your.net project that are new get package references. So like if I have Android X dot. I don't know what's a what's one of the basic ones. I don't even remember anymore. Allan Ritchie (44:49.547) Yeah, neither do I. Uh... Jon (44:52.53) Android X dot thing. Okay. Yeah, sure. Um, you know, I have that one that's, it's somewhere in my dependency chain in my Android studio project. And so when, when my Xamarin binding helpers, what it tries to do is say, I want to reference this project. It's going to ask it for all of the dependency tree of, of Maven stuff that it has, and there's a bit of a gap here in that, you know, you might have a new get package for that Android X dot thing. Allan Ritchie (44:53.574) The activity. The activity. Jon (45:20.946) And that NuGet package probably contains the AndroidX.thing.jar or.aar file in it, and it contains the binding for that. So the problem being, I don't wanna pull that over from the Android Studio project if I already have the NuGet package referenced in my project because we're gonna run into duplicate library issues compiling from the native side, right? Allan Ritchie (45:43.078) which is usually what you end up when you're doing these bindings. You almost always see that. Jon (45:46.918) Right. So, so one of the goals or one of the ideas with Sanron Binding Helpers was to try and, you know, we kind of know the conventions and packages that we produce for AndroidX stuff. And so it could reasonably try and say, you know, for this pattern, you know, it's kind of pattern matching like AndroidX.thing, I know this maps to this NuGet package that we have. And the versions kind of roughly translate like, you know, major, minor patch to Google's major minor patch. And yeah, exactly. Like, and this is the problem, right? It's not perfect, but it tries to kind of deduce and say like, okay, I don't need to bring these things because they're already in NuGet or on the other hand to say, like, I can bring these things, but you could also just reference these NuGet packages to get them. And it tries to figure out, you know, smartly during the build, what needs to be linked in from the native side of things. Allan Ritchie (46:21.659) Mostly. Jon (46:42.37) but it's not perfect and I don't think it's going to be super easy to ever make perfect. Allan Ritchie (46:48.25) Well, and they tend to move. That's the fun thing about Android and Google. The Android X libraries, people don't realize that those types. There's this, yeah, it was in here. Now it's over here. Right. And they'll do that with like a very minor version, like a dot one. They'll move a type. So it's, it's still a breaking change, but they're like, well, it's in the dependency chain, it's just in a, like a core library now and you're like, okay, but that's not a minor change, man. That is that's big. Jon (46:58.744) Yeah. Allan Ritchie (47:15.106) So, and that's common for happening. They used to do that with the support libraries way more. Like the support libraries were just a nightmare. Every time there was a major release, they would move something. And if you had a mismatch of support libraries, you'd end up with these collisions. Oh, it was rough times. Jon (47:32.266) Yeah, no, exactly. It's a bit of a challenge no matter how you slice it. And I don't think there's ever going to be, you know, one foolproof way of doing it, but I think we can get closer and closer. And certainly we can try and do some more of that sort of thinking on the iOS side of things where you could say, here's an Xcode project and, you know, it compiles it in. It maybe tries to deduce what CocoaPods you have and link those in for you. And that the other challenging part of that all too, and same with my binding helpers project is like, you don't want to always build the native project every time either. Right. So when you start to try and do like incremental build, uh, support to make it better at not just churning, like I don't want to, every time I build my app, I don't want that to cause my, my slim binding, you know, project to build and then which causes my Android studio project to call Gradle to build, cause that's adding like, you know, seconds at least. Allan Ritchie (48:28.969) A lot. Jon (48:30.454) you know, if not dozens of seconds to the whole inner dev loop that we kind of call things. Um, so that's a challenge too. And I think we can, we could do better at that. Um, there's some techniques I'm sure, like I'm sure you've probably figured out like, Hey, maybe I only, um, you know, build this thing and then I reference it a different way so that it's not constantly causing it to build every time or something like that. But that's not, not a great experience. We want to, we want to get to a better place than that. Allan Ritchie (48:57.638) Like I said, if you're doing these slim bindings and you know exactly what you need anyways, you don't need to do any weird referencing. You just have to really know, okay, these are the methods I need, pull them in, maybe hide some stuff. Like don't return an Android task, for example, return Jon (49:15.743) Right. Allan Ritchie (49:16.218) maybe make some sort of weird callback or, you know, a listener that.NET can automatically get a hold of, right, because it's pretty good. The binding mechanism is pretty good at getting a hold of that stuff. So simplifying it because it seems like every few years Android invents a new concept of how they want things to work. And then obviously the binding frameworks, you know, struggle to catch up. So if you're minimizing kind of how those things need to work or what needs to emerge from them, you're in a better place already. Jon (49:26.443) Yeah. Jon (49:45.002) Yeah, no, absolutely. Um, the, the one other thing, you know, if I was going to pitch the idea of platform channels even more, the one thing that I thought was really interesting where you can start to go with some of this too, is to try and make it a nice, uh, easy thing to do to bring it into your Maui app. So the, the one thing that I think is already in there is a, there's different types of platform channels. There's like basic ones that are just, you know, objects, uh, passing back and forth. But then I started to do like, oh, well, let's have a platform view channel that you can pass. You know, it's intended specifically for you to pass messages, but also be able to return the platform view representation from the native side. And then, oh, let's build a Maui handler on top of that so that you've got a Maui platform channel view. in Maui that you just put in your XAML and say, this is the channel ID, you know, and that'll map over to the native side. And when you implement the interface there, you have to return a view for the, the get platform view part of it. Right. And then you get messages back and forth on that where you're just accessing that from your shared code once. So if you have a library that again, map box that has a map on both platforms. And, you know, you want to be able to really easily put that into your, your Maui project and at the XAML level, you just plunk in the control, you implement the native parts on each side and you know, it's all wired up for you. So I think there's some really interesting things that we could kind of explore in the future to make the story quite nice in a lot of ways for this. But, um, yeah, I had to get that in because that one has always really been interesting to me, that concept. Allan Ritchie (51:37.862) He's not ready for us to guinea pig it though. I've been trying. Jon (51:40.306) Not quite, not quite. I'm hopeful that, you know, we, we know this is an area that, that people are struggling with always it's not. And again, it's not, I think as often as it has been in the past. So, you know, we have to always juggle like, what's the right kind of time and place to work on some of these things. Um, but I think that's one that's probably, you know, in, in our not so distant future to kind of improve upon. Uh, but we'll, I'll drop some links in the show notes to the Xamarin binding helpers because you were managing to be. I think semi successful with that. I haven't updated it for a while. So I want to go back and look at it and see if there's any, you know, obvious changes to make for net eight and all that. But then also. Allan Ritchie (52:19.367) I was naked John recently about it because I was trying to do stuff. So far so good. Jon (52:23.006) Yeah, well, and hey, like it's kind of neat if it does anything useful at this point still too. So good. Cool. Allan Ritchie (52:28.09) Like I said, I went from it being like 200 build errors to, okay, well, there's not 200 build errors and I'm able to call the one basic thing. I like, obviously there's a lot more stuff I need to add, but I'm able to call the one basic thing. So I'm, I'm out of the gate. I'm running without 200 build errors and trying to figure out that the magic, the black magic of what X nodes to remove or X path statements to put in. Jon (52:51.786) Yeah, I mean, that's like, that's often the hardest part. So that's hopefully all downhill from here, right? Allan Ritchie (52:57.606) Hopefully. Jon (53:00.05) Um, and anyway, I think, uh, that kind of also takes care of the, the plugin package or product this week too, I'm going to be selfish and just say like, let's salmon binding helpers and, or platform channels is, is maybe the, the applicable pick here. Allan Ritchie (53:15.602) Fair? I'll go with it. Jon (53:18.557) All right, I think that about does it. Allan Ritchie (53:22.45) John's hard to get a hold on in GitHub though, just so you know, unless it's Maui. Yeah, you have to. Jon (53:25.506) Yeah, be kind. PR is welcome, right? I'm expecting Alan will have some poor requests for this one. Alright everyone, thank you for listening. We'll see you next time. Allan Ritchie (53:31.334) Hehehehe