How to Build a NuGet Package for .NET MAUI Android and iOS Development

If you try to port Xamarin mobile projects to .NET MAUI, you will find there is no problem with packages built for Xamarin Android, but packages built for Xamarin iOS are incompatible. To tackle this issue, you need to change target framework to .NET 6 and rebuild related packages. Dynamsoft mobile barcode SDK so far only supports Xamarin. This article aims to help you develop mobile barcode QR code scanner apps using .NET MAUI. You will see how to build .NET binding libraries based on Android *.aar and iOS framework from scratch, as well as how to pack Android and iOS SDKs into a single NuGet package.

Barcode.NET.Mobile for MAUI

https://www.nuget.org/packages/Barcode.NET.Mobile

Prerequisites

Download Dynamsoft Mobile Barcode Scanner SDK

Creating .NET Binding Libraries for Android and iOS

Assume you have installed Visual Studio 2022 Preview on Windows and macOS. Although installing Visual Studio for Mac is not necessary that you can pair to macOS remotely, the output packages of .NET binding libraries for iOS are different between Windows and macOS. We will talk about it in the following paragraphs.

Visual Studio Library Binding Project

When searching for binding in Visual Studio 2022, you will see there are two kinds of library binding projects. One for Xamarin, and the other for .NET 6. To build .NET MAUI-compatible librayr, we select the project templates without (Xamarin).

.NET binding projects

Binding Android AAR Package for .NET 6

  1. Drag DynamsoftBarcodeReader.aar to the Android binding project.
  2. Select DynamsoftBarcodeReader.aar and change build action to AndroidLibrary.

    dotnet build action for Android aar

  3. Change the build mode to Release.
  4. Build the project. Here are the output files:
    • android.dll
    • android.pdb
    • android.xml
    • DynamsoftBarcodeReader.aar
  5. Right-click on the csproj file and select Pack to create the NuGet package.

    .NET Android nuget package

Binding iOS Framework for .NET 6

  1. Drag DynamsoftBarcodeReader.xcframework to the iOS binding project.
  2. Add following code to the csproj file.

     <ItemGroup>
         <NativeReference Include="DynamsoftBarcodeReader.xcframework">
         <Kind>Framework</Kind>
         <Frameworks></Frameworks>
         </NativeReference>
     </ItemGroup>
    
  3. Use Objective Sharpie, a command line tool for macOS, to generate ApiDefinition.cs and StructsAndEnums.cs files.
  4. Build the project. Here are the output files:
    • ios.dll
    • ios.pdb
    • ios.resources
      • DynamsoftBarcodeReader.xcframework
  5. Click Pack to create the NuGet package. Now you will see the difference between Windows and macOS. The output package generated by Visual Studio for Windows only contains ios.dll. In contrast, the package generate by Visual Studio for macOS contains ios.dll, manifest and DynamsoftBarcodeReader.xcframework. Apparently, the package built on Windows cannot work. But don’t worry, according to the structure of the package built on macOS, we can construct a workable package on Windows.

    .NET iOS nuget package

Packing Android and iOS SDKs into a Single NuGet Package

Since we have built Android and iOS packages using Visual Studio, we can publish them respectively to NuGet.org. But, what if you want to build them into a single NuGet package? We can use nuspec file to implement this.

Here are the steps:

  1. Create a nuspec file.

     nuget spec
    
  2. Add the files element and specify a list of files to be included in the package.
     <files>
         <file src="README.md" target="" />
            
         <file src="android/bin/Release/net6.0-android/android.dll" target="lib/net6.0-android31.0/" />
         <file src="android/bin/Release/net6.0-android/android.xml" target="lib/net6.0-android31.0/" />
         <file src="android/bin/Release/net6.0-android/DynamsoftBarcodeReader.aar" target="lib/net6.0-android31.0/" />
    
         <file src="ios/bin/Release/net6.0-ios/ios.dll" target="lib/net6.0-ios15.4/" />
         <file src="ios/manifest" target="lib/net6.0-ios15.4/ios.resources" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/Info.plist" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework" />
            
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Info.plist" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/DynamsoftBarcodeReader" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Headers/DynamsoftBarcodeReader.h" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Headers" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Headers/DynamsoftBarcodeSDK.h" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Headers" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Modules/module.modulemap" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64/DynamsoftBarcodeReader.framework/Modules" />
    
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Info.plist" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/DynamsoftBarcodeReader" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Headers/DynamsoftBarcodeReader.h" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Headers" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Headers/DynamsoftBarcodeSDK.h" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Headers" />
         <file src="ios/bin/Release/net6.0-ios/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Modules/module.modulemap" target="lib/net6.0-ios15.4/ios.resources/DynamsoftBarcodeReader.xcframework/ios-arm64_x86_64-simulator/DynamsoftBarcodeReader.framework/Modules" />
     </files>
    

    The manifest file used for iOS build is auto-generated by the Visual Studio for Mac.

     <BindingAssembly>
         <NativeReference Name="DynamsoftBarcodeReader.xcframework">
             <ForceLoad></ForceLoad>
             <Frameworks></Frameworks>
             <IsCxx></IsCxx>
             <Kind>Framework</Kind>
             <LinkerFlags></LinkerFlags>
             <NeedsGccExceptionHandling></NeedsGccExceptionHandling>
             <SmartLink></SmartLink>
             <WeakFrameworks></WeakFrameworks>
         </NativeReference>
     </BindingAssembly>
    

    In addition, add dependencies for different target frameworks.

     <dependencies>
       <group targetFramework="net6.0-android31.0">
       </group>
       <group targetFramework="net6.0-ios15.4">
         <dependency id="System.Runtime.InteropServices.NFloat.Internal" version="6.0.1" exclude="Build,Analyzers" />
       </group>
     </dependencies>
    
  3. Build the package:

     nuget pack
    

    .NET Android iOS nuget package

Now you can install Barcode.NET.Mobile for .NET MAUI mobile development.

Try .NET MAUI Barcode QR Code Scanner

https://github.com/yushulx/maui-barcode-qrcode-scanner

Source Code

https://github.com/yushulx/barcode-dotnet-mobile