How to Build a NuGet Package for .NET MAUI Android and iOS Development
Tags: dotnet, maui, ios, android
Published: 2022-08-19 01:44:49

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.

## Prerequisites
Download [Dynamsoft Mobile Barcode Scanner SDK](https://www.dynamsoft.com/barcode-reader/downloads)

## 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](https://www.dynamsoft.com/codepool/img/2022/08/dotnet-android-ios-binding.png)

### 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](https://www.dynamsoft.com/codepool/img/2022/08/dotnet-android-aar-build-action.png)

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](https://www.dynamsoft.com/codepool/img/2022/08/dotnet-android-nuget-package.png)

### Binding iOS Framework for .NET 6
1. Drag `DynamsoftBarcodeReader.xcframework` to the iOS binding project.
2. Add following code to the csproj file.

    ```xml
    <ItemGroup>
        <NativeReference Include="DynamsoftBarcodeReader.xcframework">
        <Kind>Framework</Kind>
        <Frameworks></Frameworks>
        </NativeReference>
    </ItemGroup>
    ```
3. Use [Objective Sharpie](https://docs.microsoft.com/en-us/xamarin/cross-platform/macios/binding/objective-sharpie/get-started), 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](https://www.dynamsoft.com/codepool/img/2022/08/dotnet-ios-nuget-package.png)


## 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](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package) file to implement this.

Here are the steps:
1. Create a `nuspec` file.

    ```bash
    nuget spec
    ```
2. Add the [files](https://docs.microsoft.com/en-us/nuget/reference/nuspec#including-assembly-files) element and specify a list of files to be included in the package. 
    ```xml
    <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. 

    ```xml
    <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.
    ```xml
    <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:

    ```bash
    nuget pack
    ```

    ![.NET Android iOS nuget package](https://www.dynamsoft.com/codepool/img/2022/08/dotnet-android-ios-nuget-package.png)

Now you can install [Barcode.NET.Mobile](https://www.nuget.org/packages/Barcode.NET.Mobile) for .NET MAUI mobile development.


## Try .NET MAUI Barcode QR Code Scanner
[https://github.com/yushulx/maui-barcode-qrcode-scanner](https://github.com/yushulx/maui-barcode-qrcode-scanner)

## Source Code
[https://github.com/yushulx/barcode-dotnet-mobile](https://github.com/yushulx/barcode-dotnet-mobile)