R
Rachel Kang (SHE/HER)
Guest
In today’s app development landscape, the ability to extend .NET applications by leveraging native capabilities is invaluable. The .NET MAUI handler architecture empowers developers to directly manipulate native controls with .NET code, even allowing for the seamless creation of cross-platform custom controls. Yet, the potential extends beyond just native platform APIs. What if you could also tap into native library APIs, unlocking even more possibilities?
Native Library Interop for .NET MAUI, previously known as the Slim Binding approach, is an alternative method for integrating native libraries into .NET MAUI applications, including .NET for Android, .NET for iOS, and .NET for Mac Catalyst. This approach enables direct access to native library APIs in a way that is both streamlined and maintenance-friendly, eliminating the need to bind entire libraries through traditional methods.
The Maui.NativeLibraryInterop repository serves as a valuable resource of community-curated samples, offering .NET developers an opportunity to delve into and benefit from shared knowledge, as well as contribute their own insights. With a ready-to-use template for creating new bindings, it serves as an excellent foundation for developers embarking on their journey from concept to execution.
In this post, I am excited to share my own journey with Native Library Interop for .NET MAUI, presenting a practical example to illustrate how this innovative approach can be leveraged in your .NET MAUI applications. Join me as I implement a binding, using the template and following the guidance in the Getting Started documentation.
To get started, I first cloned the Maui.NativeLibraryInterop repository. If interested in building off one of the existing bindings samples (Facebook, Firebase, GoogleCast), I would start from the samples contained in the respective folders. As I am interested in creating a binding from a completely different library, however, I’m going to start with the template! The template contains the foundation for getting started with using Native Library Interop to create an Android binding, iOS and Mac Catalyst binding, and a .NET MAUI sample app that uses both.
Getting the prerequisites
Before proceeding, make sure you have all the prerequisites installed. If you are a long-time .NET MAUI developer, it is likely you already have most if not all of them installed like myself, but be sure to check the full list of prerequisites.
I copy and paste the template into my desired location, deploy the sample to all three platforms, and tada! Everything works as expected. I see “Hello, Community Toolkit from java!” on the Android app, demonstrating the Android binding working as expected, and “Hello, Community Toolkit from swift!” on the iOS and Mac Catalyst apps, demonstrating the MaciOS binding working as expected.
So what am I looking to bind? Well, I want to include a nice pie chart in my app! And the .NET MAUI SDK does not currently have a built-in control for that.
While all the charts I can create using the Charts library are so beautiful, I have chosen the Native Library Interop approach because I only need a pie chart in my .NET MAUI app right now, so I want to bind the APIs I need just for the pie chart, and nothing more.
To create my binding for charts, I will be using the MPAndroidChart library for Android and the equivalent Charts library for iOS and Mac Catalyst.
As such, I would like the name of my binding to reflect that. For Android, I rename the class, file name, and all references of
Cool, easy enough. What’s next?
I’m planning on binding libraries for Android, iOS, and Mac Catalyst, and I’m lucky to have the option to support all three with the libraries I found! If not interested in all platforms, I’d simply delete the folder, target framework, and references for the one I’m not interested in.
As for the .NET version, I’m going to stick with using .NET 8 for now. When I’m ready to use .NET 9, however, I will eventually update the TargetFrameworks and versions in Charts.MaciOS.Binding.csproj and Charts.Android.Binding.csproj respectively.
And that’s it! While I have the choice to customize here, I did not need to take any extra steps to set up the .NET binding libraries beyond what the template has already set up for me.
Now, let’s make sure the same is reflected in the native projects, and bring in the native libraries!
First, I open the native project macios/native/Charts/Charts.xcodeproj in Xcode. I check in Targets > General that the supported destinations and iOS version match what I need, so once again, I’m already good to go here.
Now, it’s time to bring in the native Charts library! As there are various options for bringing in a native library, this step will vary based on what works best with the specific library and personal preferences. In my case, I’m going to opt to use Swift Package Manager by navigating to File > Add Package Dependencies…
searching for the Charts library package,
and clicking Add Package. The Charts library has been added to my native Xcode project!
Now, it’s time to do the same thing in Android land! First, I open the native project android/native in Android Studio. Once the project loads, I open build.gradle.kts charts) and confirm that the
Now, to bring in the native Charts library, I make the following edits in build.gradle.kts:
I also add the relevant maven repository in settings.gradle.kts:
Last but not least, I click on the Sync Project with Gradle Files button in the upper-right-hand corner to make the cute gradle elephant happy.
Now that we have brought in the native libraries, it’s time to build the APIs we will be using in our .NET apps! The cool part of the Native Library Interop approach is that all of this happens on the native side. This means we can leverage any existing documentation that the libraries provide to write in the native languages directly – Swift / Objective-C for iOS and Mac Catalyst, and Java / Kotlin for Android. It also means we can update those APIs a lot more easily with less of the overhead that comes with manually translating everything into .NET terms.
In DotnetCharts.swift, I define all the APIs my heart desires. While that quite literally means I can define any API in Swift, as the template string example also shows, I will stay focused for now on my mission of creating an API interface for Charts, and will
Then, I write up the API definition for creating a pie chart. As a .NET developer, I can’t say I’m the biggest Swift expert, but being able to leverage the Swift samples directly from the Charts library repo, and getting assistance from GitHub Copilot is certainly a game changer that makes this part so much less daunting.
Once I ensure my Swift code is valid by building the Xcode project successfully, I run back as quickly as I can to the .NET side of things to make sure the native library indeed interops.
From macios/Charts.MaciOS.Binding I run
Then, I run
Back again now in Android world! In DotnetCharts.java, I can define any API in Java, as the template string examples shows here as well. To stay focused on Charts, however, I will import everything I need. While the libraries are pretty parallel, they are implemented slightly differently, which will affect how I import and define my APIs here as well.
As such, I import the following from
Then, I once again write up the API definition for creating a pie chart. Just as I’m not the biggest Swift expert, I am also not the biggest Android expert… but I am still a mobile app developer! Being able to directly leverage online resources and GitHub Copilot makes this all very feasible.
Running back again to the comfort of .NET, I navigate to android/Charts.Android.Binding and run
This generates a copy of the dependencies at android/native/charts/bin/Release/net8.0-android/outputs/deps/MPAndroidChart-v3.1.0.aar which, unlike with iOS and Mac Catalyst, I will need to directly reference in my .NET sample app by adding the following to MauiSample.csproj:
It’s time for the moment of truth! The Charts binding can now be used in any new or existing .NET MAUI apps, including any .NET for iOS, .NET for Mac Catalyst, and .NET for Android apps. For simplicity, I will use it in the .NET MAUI sample app that came with the template which already references the .NET binding libraries for me in the MauiSample.csproj:
In MainPage.xaml.cs, I import
And voila! I present to you beautiful pie charts in .NET MAUI!
Thanks for following along on my journey of creating a charts binding with Native Library Interop! To check out all of the code, including the details of my API definitions and sample usage, you can find the full sample at GitHub - rachelkang/MauiCharts: Charts binding created using Native Library Interop for .NET MAUI. To learn more about the Native Library Interop approach, uncover the magic built in to simplify this process, and better understand when to use it, be sure to check out our documentation.
I hope that seeing my process gives you some exciting ideas for the endless possibilities that using Native Library Interop has in store for you!
Be sure to check it out yourself at CommunityToolkit/Maui.NativeLibraryInterop. I’d love to see what bindings you create, and hear about how this process goes for you!
The post Easily Create Bindings for .NET MAUI with Native Library Interop appeared first on .NET Blog.
Continue reading...
Native Library Interop for .NET MAUI, previously known as the Slim Binding approach, is an alternative method for integrating native libraries into .NET MAUI applications, including .NET for Android, .NET for iOS, and .NET for Mac Catalyst. This approach enables direct access to native library APIs in a way that is both streamlined and maintenance-friendly, eliminating the need to bind entire libraries through traditional methods.
The Maui.NativeLibraryInterop repository serves as a valuable resource of community-curated samples, offering .NET developers an opportunity to delve into and benefit from shared knowledge, as well as contribute their own insights. With a ready-to-use template for creating new bindings, it serves as an excellent foundation for developers embarking on their journey from concept to execution.
In this post, I am excited to share my own journey with Native Library Interop for .NET MAUI, presenting a practical example to illustrate how this innovative approach can be leveraged in your .NET MAUI applications. Join me as I implement a binding, using the template and following the guidance in the Getting Started documentation.
Getting started with the Native Library Interop template
To get started, I first cloned the Maui.NativeLibraryInterop repository. If interested in building off one of the existing bindings samples (Facebook, Firebase, GoogleCast), I would start from the samples contained in the respective folders. As I am interested in creating a binding from a completely different library, however, I’m going to start with the template! The template contains the foundation for getting started with using Native Library Interop to create an Android binding, iOS and Mac Catalyst binding, and a .NET MAUI sample app that uses both.
Getting the prerequisites
Before proceeding, make sure you have all the prerequisites installed. If you are a long-time .NET MAUI developer, it is likely you already have most if not all of them installed like myself, but be sure to check the full list of prerequisites.
I copy and paste the template into my desired location, deploy the sample to all three platforms, and tada! Everything works as expected. I see “Hello, Community Toolkit from java!” on the Android app, demonstrating the Android binding working as expected, and “Hello, Community Toolkit from swift!” on the iOS and Mac Catalyst apps, demonstrating the MaciOS binding working as expected.
What will I bind?
So what am I looking to bind? Well, I want to include a nice pie chart in my app! And the .NET MAUI SDK does not currently have a built-in control for that.
While all the charts I can create using the Charts library are so beautiful, I have chosen the Native Library Interop approach because I only need a pie chart in my .NET MAUI app right now, so I want to bind the APIs I need just for the pie chart, and nothing more.
To create my binding for charts, I will be using the MPAndroidChart library for Android and the equivalent Charts library for iOS and Mac Catalyst.
As such, I would like the name of my binding to reflect that. For Android, I rename the class, file name, and all references of
DotnetNewBinding
at android/native/newbinding/src/main/java/com/example/newbinding/DotnetNewBinding.java. For MaciOS, I do the same for macios/native/NewBinding/NewBinding/DotnetNewBinding.swift. While optional, I took the liberty to rename all folders, files, and instances of “newBinding” to “charts” in my project as well.Cool, easy enough. What’s next?
Setting up the .NET binding libraries
I’m planning on binding libraries for Android, iOS, and Mac Catalyst, and I’m lucky to have the option to support all three with the libraries I found! If not interested in all platforms, I’d simply delete the folder, target framework, and references for the one I’m not interested in.
As for the .NET version, I’m going to stick with using .NET 8 for now. When I’m ready to use .NET 9, however, I will eventually update the TargetFrameworks and versions in Charts.MaciOS.Binding.csproj and Charts.Android.Binding.csproj respectively.
And that’s it! While I have the choice to customize here, I did not need to take any extra steps to set up the .NET binding libraries beyond what the template has already set up for me.
Setting up the native wrapper projects and libraries
Now, let’s make sure the same is reflected in the native projects, and bring in the native libraries!
iOS & Mac Catalyst
First, I open the native project macios/native/Charts/Charts.xcodeproj in Xcode. I check in Targets > General that the supported destinations and iOS version match what I need, so once again, I’m already good to go here.
Now, it’s time to bring in the native Charts library! As there are various options for bringing in a native library, this step will vary based on what works best with the specific library and personal preferences. In my case, I’m going to opt to use Swift Package Manager by navigating to File > Add Package Dependencies…
searching for the Charts library package,
and clicking Add Package. The Charts library has been added to my native Xcode project!
Android
Now, it’s time to do the same thing in Android land! First, I open the native project android/native in Android Studio. Once the project loads, I open build.gradle.kts charts) and confirm that the
compileSdk
version reflects my needs.Now, to bring in the native Charts library, I make the following edits in build.gradle.kts:
Code:
dependencies {
// Add package dependency for binding library
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
// Copy dependencies for binding library
"copyDependencies"("com.github.PhilJay:MPAndroidChart:v3.1.0")
}
I also add the relevant maven repository in settings.gradle.kts:
Code:
dependencyResolutionManagement {
...
repositories {
...
// Add repository here
maven { url = uri("https://jitpack.io") }
}
}
Last but not least, I click on the Sync Project with Gradle Files button in the upper-right-hand corner to make the cute gradle elephant happy.
Creating the API interface
Now that we have brought in the native libraries, it’s time to build the APIs we will be using in our .NET apps! The cool part of the Native Library Interop approach is that all of this happens on the native side. This means we can leverage any existing documentation that the libraries provide to write in the native languages directly – Swift / Objective-C for iOS and Mac Catalyst, and Java / Kotlin for Android. It also means we can update those APIs a lot more easily with less of the overhead that comes with manually translating everything into .NET terms.
iOS & Mac Catalyst
In DotnetCharts.swift, I define all the APIs my heart desires. While that quite literally means I can define any API in Swift, as the template string example also shows, I will stay focused for now on my mission of creating an API interface for Charts, and will
import DGCharts
at the top of the file.Then, I write up the API definition for creating a pie chart. As a .NET developer, I can’t say I’m the biggest Swift expert, but being able to leverage the Swift samples directly from the Charts library repo, and getting assistance from GitHub Copilot is certainly a game changer that makes this part so much less daunting.
Once I ensure my Swift code is valid by building the Xcode project successfully, I run back as quickly as I can to the .NET side of things to make sure the native library indeed interops.
From macios/Charts.MaciOS.Binding I run
dotnet build
. This generates the .NET API definitions in macios/native/Charts/bin/Release/net8.0-ios/sharpie/Charts/ApiDefinitions.cs which I then copy into charts/macios/Charts.MaciOS.Binding/ApiDefinition.cs.Then, I run
dotnet build
once more to ensure everything is happy. Android
Back again now in Android world! In DotnetCharts.java, I can define any API in Java, as the template string examples shows here as well. To stay focused on Charts, however, I will import everything I need. While the libraries are pretty parallel, they are implemented slightly differently, which will affect how I import and define my APIs here as well.
As such, I import the following from
com.github.mikephil.charting
:
Code:
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.utils.ColorTemplate;
Then, I once again write up the API definition for creating a pie chart. Just as I’m not the biggest Swift expert, I am also not the biggest Android expert… but I am still a mobile app developer! Being able to directly leverage online resources and GitHub Copilot makes this all very feasible.
Running back again to the comfort of .NET, I navigate to android/Charts.Android.Binding and run
dotnet build
.This generates a copy of the dependencies at android/native/charts/bin/Release/net8.0-android/outputs/deps/MPAndroidChart-v3.1.0.aar which, unlike with iOS and Mac Catalyst, I will need to directly reference in my .NET sample app by adding the following to MauiSample.csproj:
Code:
<!-- Reference the Android binding dependencies -->
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
<AndroidLibrary Include="..\android\native\charts\bin\Release\net8.0-android\outputs\deps\MPAndroidChart-v3.1.0.aar">
<Bind>false</Bind>
<Visible>false</Visible>
</AndroidLibrary>
</ItemGroup>
Consuming the APIs in your .NET app
It’s time for the moment of truth! The Charts binding can now be used in any new or existing .NET MAUI apps, including any .NET for iOS, .NET for Mac Catalyst, and .NET for Android apps. For simplicity, I will use it in the .NET MAUI sample app that came with the template which already references the .NET binding libraries for me in the MauiSample.csproj:
Code:
<!-- Reference to MaciOS Binding project -->
<ItemGroup Condition="$(TargetFramework.Contains('ios')) Or $(TargetFramework.Contains('maccatalyst'))">
<ProjectReference Include="..\macios\Charts.MaciOS.Binding\Charts.MaciOS.Binding.csproj" />
</ItemGroup>
<!-- Reference to Android Binding project -->
<ItemGroup Condition="$(TargetFramework.Contains('android'))">
<ProjectReference Include="..\android\Charts.Android.Binding\Charts.Android.Binding.csproj" />
</ItemGroup>
In MainPage.xaml.cs, I import
ChartsMaciOS.DotnetCharts
and ChartsAndroid.DotnetCharts
and use platform directives to directly leverage the APIs I created, just as I would with any other platform-specific implementation in .NET MAUI.And voila! I present to you beautiful pie charts in .NET MAUI!
What will you bind?
Thanks for following along on my journey of creating a charts binding with Native Library Interop! To check out all of the code, including the details of my API definitions and sample usage, you can find the full sample at GitHub - rachelkang/MauiCharts: Charts binding created using Native Library Interop for .NET MAUI. To learn more about the Native Library Interop approach, uncover the magic built in to simplify this process, and better understand when to use it, be sure to check out our documentation.
I hope that seeing my process gives you some exciting ideas for the endless possibilities that using Native Library Interop has in store for you!
Be sure to check it out yourself at CommunityToolkit/Maui.NativeLibraryInterop. I’d love to see what bindings you create, and hear about how this process goes for you!
The post Easily Create Bindings for .NET MAUI with Native Library Interop appeared first on .NET Blog.
Continue reading...