Немного теории

Для использования готовых нативных библиотек в MAUI нам предлагают механизмы Binding native library и Native Library Interop. Binding native library работает с собранными библиотеками (aar или jar для Android, XCFrameworks для iOS/Macos), Native Library Interop (или slim bindings) - это способ добавлять в проект ссылки на нативные проекты (Xcode или gradle), в процессе компиляции проекта обещают автоматическую соборку нативной библиотеки и генерацию обёртки для неё. Кроме того есть еще старый добрый P/Invoke, но это совсем другая история.

Чего не хватает?

В списке доступных SDK RuStore много чего на все случаи жизни. Тут нам и пуши, встроенные покупки, работа с обновлениями, отзывами и прочие штуки. Кроме того тут не указаны sdk для сторонних сервисов, которые можно подключить к приложению, например, tracer от ОК.
Теоретически к приложению на MAUI для андроид можно всё это дело подключить.
Основной минус - у вас должен быть аккаунт RuStore.

Еще немного теории.

Раньше, до .Net 9, для добавления нативных зависимостей Android (*.jar или *.aar) нужно было скачать aar, подложить его в проект или куда-то рядом (с помощью IDE или руками).
Если добавляли руками, нужно было указать ссылку на файл.

<ItemGroup>
  <AndroidLibrary Update="aar/my_lib.aar"/>
</ItemGroup>

С релизом .Net 9 появилась опция AndroidMavenLibrary. Как вы,наверняка поняли из названия - с помощью неё можно задать ссылку на библиотеку в удалённом репозитории Maven. Очень важно что у этой опции есть свойство Repository, с помощью которого можно указать Url для cкачивания aar. Описание по ссылке выше.

Делаем получение пушей из RuStore

Нам нужен солюшен из двух проектов:

1. Андроид биндинг (в VS Code этот шаблон называется "привязка библиотеки Java для Android"), в котором будет генерироваться обёртка для Maui
2. Проект для тестового приложения, со ссылкой на первый проект.

Открываем файл первого проекта как текст и вставляем в корневой элемент этот кусок

<ItemGroup>
  <AndroidMavenLibrary 
    Include="ru.rustore.sdk:pushclient" 
    Version="7.0.0" 
    Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" />
</ItemGroup>

Должно получиться примерно так:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net9.0-android</TargetFramework>
    <SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <IsTrimmable>true</IsTrimmable>
  </PropertyGroup>
  <ItemGroup>
    <AndroidMavenLibrary 
      Include="ru.rustore.sdk:pushclient" 
      Version="7.0.0"
      Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" />
  </ItemGroup>
</Project>

Так мы добавили ссылку на библиотеку pushclient версии 7.0.0 и указали источник для скачивания, который указан в разделе "Подключение в проект" официальной документации RuStore Push SDK.

Жмём собрать проект в IDE или dotnet build в консоли и получаем кучу ошибок.

Тут мы видим что вместе с aar скачался *.pom файл с описанием зависимостей и каким-то образом их надо добавить в проект. Пока что автоматическое скачивание зависимостей не допилили, да.

Если вглядеться, то в описании некоторых ошибок пишется  "Корпорация Майкрософт поддерживает пакет NuGet "Square.OkHttp3", который может выполнить эту зависимость." Это значит что можно добавить NuGet c обёрткой наподобие той что мы пытаемся сделать, а можно добавить ссылку с помощью AndroidMavenLibrary, по аналогии с основным пакетом. Можно ошибки закинуть в нейронку, но тут важно следить за версиями библиотек в ответе. Можно залипнуть на несколько дней просто из-за того что в ответе нейронки будет другая версия библиотеки. В итоге у меня получился вот такой-вот список зависимостей.

Скрытый текст
<ItemGroup>
        <!-- RuStore SDK из собственного репозитория -->
        <AndroidMavenLibrary Include="ru.rustore.sdk:pushclient" Version="7.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" />
        <AndroidMavenLibrary Include="ru.rustore.sdk:core" Version="8.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:push-core" Version="7.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:push-core-remote-config" Version="7.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:push-common" Version="7.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven"/>

        <AndroidMavenLibrary Include="ru.rustore.sdk:push-core-network" Version="7.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:coreui" Version="8.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:metrics" Version="8.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false" />

        <AndroidMavenLibrary Include="ru.rustore.sdk:reactive" Version="8.0.0" Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" Bind="false"/>

        <!-- HMS из Huawei репозитория -->
        <AndroidMavenLibrary Include="com.huawei.hms:push" Version="6.12.0.300" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:opendevice" Version="6.12.0.300" Repository="https://developer.huawei.com/repo/" Bind="false" JavaArtifact="com.huawei.android.hms:security-encrypt:1.2.0.307;com.huawei.android.hms:security-base:1.2.0.307;com.huawei.hms:base:6.11.0.302;javax.inject:javax.inject:1" />
        <AndroidMavenLibrary Include="com.huawei.android.hms:security-encrypt" Version="1.2.0.307" Repository="https://developer.huawei.com/repo/" Bind="false" JavaArtifact="com.huawei.android.hms:security-base:1.2.0.307;com.huawei.hms:base:6.11.0.302;javax.inject:javax.inject:1" />
        <AndroidMavenLibrary Include="com.huawei.android.hms:security-base" Version="1.2.0.307" Repository="https://developer.huawei.com/repo/" Bind="false" JavaArtifact="com.huawei.hms:base:6.11.0.302;javax.inject:javax.inject:1" />
        <AndroidMavenLibrary Include="com.huawei.hms:base" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:baselegacyapi" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:stats" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:ui" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:device" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:log" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hmf:tasks" Version="1.5.2.206" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:availableupdate" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:hatool" Version="6.11.0.302" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:network-grs" Version="6.0.11.300" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.agconnect:agconnect-core" Version="1.8.1.300" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.android.hms:security-ssl" Version="1.2.0.307" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:network-common" Version="6.0.11.300" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <AndroidMavenLibrary Include="com.huawei.hms:network-framework-compat" Version="6.0.11.300" Repository="https://developer.huawei.com/repo/" Bind="false" />
        <!-- RuStore SDK внешние зависимости -->
        <AndroidMavenLibrary Include="ru.ok.tracer:tracer-base" Version="1.1.1" Bind="false" />
        <AndroidMavenLibrary Include="ru.ok.tracer:tracer-manifest" Version="1.1.1" Bind="false" />
        <AndroidMavenLibrary Include="ru.ok.tracer:tracer-lite-commons" Version="1.1.1" Bind="false" />
        <AndroidMavenLibrary Include="ru.ok.tracer:tracer-lite-crash-report" Version="1.1.1" Bind="false" />

    </ItemGroup>
    <ItemGroup>

        <PackageReference Include="Square.OkHttp3" Version="4.10.0" />
        <PackageReference Include="Square.OkIO.JVM" Version="3.0.0"/>

        <!-- Kotlin runtime -->
        <PackageReference Include="Xamarin.AndroidX.SavedState" Version="1.3.3" />
        <PackageReference Include="Xamarin.AndroidX.SavedState.SavedState.Android" Version="1.3.3" />
        <PackageReference Include="Xamarin.AndroidX.SavedState.SavedState.Ktx" Version="1.3.3" />
        <PackageReference Include="Xamarin.Kotlin.StdLib" Version="2.2.20" />
        <PackageReference Include="Xamarin.Kotlin.StdLib.Common" Version="2.0.21.5" />
        <PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="2.2.20" />
        <PackageReference Include="Xamarin.KotlinX.Coroutines.Core" Version="1.10.2.1" />
        <PackageReference Include="Xamarin.KotlinX.Coroutines.Core.Jvm" Version="1.10.2.1" />
        <PackageReference Include="Xamarin.KotlinX.Coroutines.Android" Version="1.10.2.1" />

        <!-- AndroidX base -->
        <PackageReference Include="Xamarin.AndroidX.Core" Version="1.17.0" />
        <PackageReference Include="Xamarin.AndroidX.Core.Core.Ktx" Version="1.17.0" />
        <PackageReference Include="Xamarin.AndroidX.Annotation" Version="1.9.1.5" />
        <PackageReference Include="Xamarin.AndroidX.Annotation.Experimental" Version="1.5.1.1" />
        <PackageReference Include="Xamarin.AndroidX.Startup.StartupRuntime" Version="1.2.0.5" />
        <PackageReference Include="Xamarin.AndroidX.Work.Work.Runtime.Ktx" Version="2.10.5" />
        <PackageReference Include="Xamarin.AndroidX.Room.Room.Ktx" Version="2.8.1" />
        <PackageReference Include="Xamarin.AndroidX.Sqlite.Framework" Version="2.6.1" />
        <PackageReference Include="Xamarin.AndroidX.DataStore.Preferences" Version="1.1.7.1" />

        <!-- Lifecycle family (чтобы не было конфликтов) -->
        <PackageReference Include="Xamarin.AndroidX.Lifecycle.Common" Version="2.9.4" />
        <PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime" Version="2.9.4" />
        <PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime.Android" Version="2.9.4" />
        <PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.9.4" />
        <PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core" Version="2.9.4" />

        <!-- Material & UI -->
        <PackageReference Include="Xamarin.Google.Android.Material" Version="1.13.0" />


        <!-- Firebase core set -->
        <PackageReference Include="Xamarin.Firebase.Common" Version="122.0.1" />
        <PackageReference Include="Xamarin.Firebase.Common.Ktx" Version="121.0.0.7" />
        <PackageReference Include="Xamarin.Firebase.Components" Version="119.0.0.1" />
        <PackageReference Include="Xamarin.Firebase.Datatransport" Version="120.0.1" />
        <PackageReference Include="Xamarin.Firebase.Encoders" Version="117.0.0.23" />
        <PackageReference Include="Xamarin.Firebase.Encoders.JSON" Version="118.0.1.15" />
        <PackageReference Include="Xamarin.Firebase.Encoders.Proto" Version="116.0.0.18" />
        <PackageReference Include="Xamarin.Firebase.Installations" Version="119.0.1" />
        <PackageReference Include="Xamarin.Firebase.Installations.InterOp" Version="117.2.0.11" />
        <PackageReference Include="Xamarin.Firebase.Measurement.Connector" Version="120.0.1.11" />

        <!-- Google Play Services -->
        <PackageReference Include="Xamarin.GooglePlayServices.Base" Version="118.9.0" />
        <PackageReference Include="Xamarin.GooglePlayServices.Basement" Version="118.9.0" />
        <PackageReference Include="Xamarin.GooglePlayServices.Tasks" Version="118.4.0" />
        <PackageReference Include="Xamarin.GooglePlayServices.CloudMessaging" Version="117.3.0.7" />

        <PackageReference Include="Xamarin.GooglePlayServices.Stats" Version="117.1.0.7" />
        <PackageReference Include="Xamarin.Google.Android.DataTransport.TransportApi" Version="4.0.0.5" />

        <!-- Guava / DataTransport -->
        <PackageReference Include="Xamarin.Google.Guava.ListenableFuture" Version="1.0.0.29" />
        <PackageReference Include="Xamarin.Google.Android.DataTransport.TransportBackendCct" Version="4.0.0.5" />
        <PackageReference Include="Xamarin.Google.Android.DataTransport.TransportRuntime" Version="4.0.0.5" />

        <PackageReference Include="Xamarin.JavaX.Inject" Version="1.0.0.21" />
    </ItemGroup>

В этом примере важны атрибуты Bind.

<AndroidMavenLibrary 
  Include="ru.rustore.sdk:push-core" Version="7.0.0" 
  Repository="https://artifactory-external.vkpartner.ru/artifactory/maven" 
  Bind="false" />

По умолчанию Bind="true", а это значит что будет сгенерирована обёртка на C#. Для зависимостей это нужно только когда типы из этих библиотек используются в качестве входных-выходных параметров public функций основной сборке, а если обёртка не нужна то и править возможные ошибки тоже не нужно.
После сборки, Visual Studio Code насыпал кучу ошибок. Ошибки кликабельные. Если кликнуть на первую ошибку увидим что-то такое:

Из скриншота видно что какая-то обертка всё таки получилась, но c имплементацией интерфейса что-то пошло не так, причём в двух местах: NotificationParams.CREATOR и RemoteMessage.CREATOR. Так как эти классы нам пока не нужны давайте укажем сборщику не делать обёртку.
Для этого открываем файл Transorms/Metadata.xml.Атрибут path копируем в комментарии над объявлением класса. Получилось вот так:

<metadata>
    <remove-node path="/api/package[@name='com.vk.push.common.messaging']/class[@name='NotificationParams.CREATOR']"/>
    <remove-node path="/api/package[@name='com.vk.push.common.messaging']/class[@name='RemoteMessage.CREATOR']"/>
</metadata>

После сборки можно заметить что ошибки с этими классами исчезли. Жмём на следующую ошибку: 'ILoggerInvoker' does not implement interface member 'ILogger.CreateLogger(string)'. 'ILoggerInvoker.CreateLogger(string)' cannot implement 'ILogger.CreateLogger(string)' because it does not have the matching return type of 'ILogger'.

Ошибка такая же, но в этом случае логгер нам может пригодится, мало ли чего?
Самое интересное что если пролистать вниз этот метод всё таки будет реализован:

// Metadata.xml XPath method reference: path="/api/package[@name='ru.rustore.sdk.pushclient.common.logger']/class[@name='DefaultLogger']/method[@name='createLogger' and count(parameter)=1 and parameter[1][@type='java.lang.Object']]"
[Register ("createLogger", "(Ljava/lang/Object;)Lcom/vk/push/common/Logger;", "")]
public unsafe global::Com.VK.Push.Common.ILogger CreateLogger (global::Java.Lang.Object p0)
{
    const string __id = "createLogger.(Ljava/lang/Object;)Lcom/vk/push/common/Logger;";
    try {
        JniArgumentValue* __args = stackalloc JniArgumentValue [1];
        __args [0] = new JniArgumentValue ((p0 == null) ? IntPtr.Zero : ((global::Java.Lang.Object) p0).Handle);
        var __rm = _members.InstanceMethods.InvokeAbstractObjectMethod (__id, this, __args);
        return global::Java.Lang.Object.GetObject<global::Com.VK.Push.Common.ILogger> (__rm.Handle, JniHandleOwnership.TransferLocalRef)!;
    } finally {
        global::System.GC.KeepAlive (p0);
    }
}

Странно, ну ладно... Давайте посмотрим что за зверь такой ru.rustore.sdk.pushclient.common.logger.
Для этого переходим во внутрь aar (я это делаю с помощью mc):

mc /obj/Debug/net9.0-android/library_project_jars/pushclient-7.0.0.aar

Там переходим в консольный режим (ctrl+o), запускаем jadx-gui classes.jar

Видно что это действительно интерфейс и в нём есть метод createLogger. Просят реализовать - давайте реализуем. Для этого в корне проекта создадим класс ILoggerInvoker:

namespace RU.Rustore.Sdk.Pushclient.Common.Logger;

internal partial class ILoggerInvoker
{
    Com.VK.Push.Common.ILogger Com.VK.Push.Common.ILogger.CreateLogger(string tag)
    {
        return CreateLogger(tag);
    }
}

Для DefaultLogger решение аналогичное:

namespace RU.Rustore.Sdk.Pushclient.Common.Logger;

public partial class DefaultLogger
{
    Com.VK.Push.Common.ILogger Com.VK.Push.Common.ILogger.CreateLogger(string tag)
    {
        return CreateLogger(tag);
    }
}

Собираем и ... ошибок сборки нет. Теперь переходим к тестовому проекту.
Добавляем в манифест приложения для андроид:

<meta-data
  android:name="ru.rustore.sdk.pushclient.default_notification_channel_id"
  android:value="@string/notifications_data_push_channel_id" />

Добавляем пермишен:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

strings.xml в ресурсы андроида

<resources>
    <string name="app_name">RuStore Push Java Example</string>
    <!-- Notification -->
    <string name="notifications_data_push_channel_id">data_push_channel</string>
    <string name="notifications_data_push_channel_name">Data push channel</string>
    <string name="notifications_notification_push_channel_id">notification_push_channel</string>
    <string name="notifications_notification_push_channel_name">Notification push channel</string>
</resources>

NotificationManagerWrapper для создания и показа пуша

using Android.Content;
using Android.Content.PM;
using AndroidX.Core.App;
using AndroidX.Core.Content;

namespace Sample.Wrapper;

public record AppNotification(int Id, string Title, string Message, string ChannelId, string ChannelName);
public class NotificationManagerWrapper
{
    private readonly NotificationManagerCompat _notificationManager;
    private static NotificationManagerWrapper _instance;

    private NotificationManagerWrapper(NotificationManagerCompat notificationManager)
    {
        _notificationManager = notificationManager;
    }

    public static NotificationManagerWrapper GetInstance(Context context)
    {
        if (_instance == null)
        {
            _instance = new NotificationManagerWrapper(NotificationManagerCompat.From(context));
        }
        return _instance;
    }

    public void CreateNotificationChannel(string channelId, string channelName)
    {
        var builder = new NotificationChannelCompat.Builder(channelId, NotificationManagerCompat.ImportanceDefault)
            .SetName(channelName);

        _notificationManager.CreateNotificationChannel(builder.Build());
    }

    public void ShowNotification(Context context, AppNotification data)
    {
        // Создаём билдер уведомления
        var builder = new NotificationCompat.Builder(context, data.ChannelId)
            .SetContentTitle(data.Title)
            .SetContentText(data.Message)
            .SetSmallIcon(Resource.Drawable.dotnet_bot); // замените на свой значок

        // Проверяем наличие канала
        if (_notificationManager.GetNotificationChannel(data.ChannelId) == null)
        {
            CreateNotificationChannel(data.ChannelId, data.ChannelName);
        }

        // Проверка разрешения на уведомления (Android 13+)
        if (ContextCompat.CheckSelfPermission(context, Android.Manifest.Permission.PostNotifications) != Permission.Granted)
        {
            return;
        }

        _notificationManager.Notify(data.Id, builder.Build());
    }
}

Фоновый андроид-сервис для приёма пушей:

using Android.App;
using Android.Util;
using Microsoft.Maui.Controls.Internals;
using RU.Rustore.Sdk.Pushclient.Messaging.Exception;
using RU.Rustore.Sdk.Pushclient.Messaging.Model;
using RU.Rustore.Sdk.Pushclient.Messaging.Service;
using Sample.Wrapper;

namespace Sample;

[Preserve(AllMembers = true)]
[Service(Exported = true)]
[IntentFilter(new[] { "ru.rustore.sdk.pushclient.MESSAGING_EVENT" })]
public class PushListenerService : RuStoreMessagingService
{
    private const string LogTag = "PushListenerService";
    private NotificationManagerWrapper? _notificationManagerWrapper;

    public override void OnCreate()
    {
        base.OnCreate();
        _notificationManagerWrapper = NotificationManagerWrapper.GetInstance(this);
    }

    public override void OnNewToken(string token)
    {
        Log.Debug(LogTag, $"OnNewToken token = {token}");
    }

    public override void OnMessageReceived(RemoteMessage message)
    {
        base.OnMessageReceived(message);

        var channelInfo = GetChannelInfo();

        var notification = new AppNotification(
            message.GetHashCode(),
            message.Notification?.Title,
            message.Notification?.Body,
            channelInfo.Item1,
            channelInfo.Item2
        );

        _notificationManagerWrapper.ShowNotification(this, notification);
    }

    private (string, string) GetChannelInfo()
    {
        string channelId = GetString(Resource.String.notifications_data_push_channel_id);
        string channelName = GetString(Resource.String.notifications_data_push_channel_name);
        return (channelId, channelName);
    }

    public override unsafe void OnError(IList<RuStorePushClientException> errors)
    {
        base.OnError(errors);
    }
}

Всё это очень напоминает подключение пушей Firebase.
Не забываем включить поддержку unsafe, но если что компилятор напомнит.

Далее переходим в раздел Проверка возможности получать push-уведомления официальной документации. Проверяем ничего ли мы не забыли. Самое главное нужно добавить fingerprint(отпечаток) подписи (без этого не получить project id) и настроить подпись apk при сборке. Без этого пуши не заработают и будут сыпаться эксепшены.
В MainApplication добавляем инициализацию, всё как в документации:

public override void OnCreate()
{
    base.OnCreate();
    RuStorePushClient.Instance.Init(this,
            "push project id", new MainActivity.MyLogger());
}

А в MainActivity запрашиваем перемешен

protected override void OnCreate(Bundle? savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    const int requestNotification = 0;
    string[] notiPermission =
    {
        Manifest.Permission.PostNotifications
    };

    if (CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted)
    {
        RequestPermissions(notiPermission, requestNotification);
    }
}

Запускаем, открываем Logcat ищем push-токен по тэгу PushListenerService, копируем токен в интерфейс отправки тестовых сообщений в Rustore. Жмём отправить.

Победа! Пуши приходят, но почему-то задваиваются при показе в шторке. Думал что это где-то у меня ошибка. Запустил официальный пример на Котлин - там такое же поведение, просто второй пуш не показывается, т.к. в сервисе эксепшен из-за того что иконка мне указана.

Выводы:

  • Биндинг либы из Rustore SDK делать несложно, хотя количество ошибок сборки может испугать неподготовленного человека.

  • Документация для java/kotlin подробная, библиотека хорошо обложена логированием в логкат. Во время отладки сыпались эксепшены, из которых понятно как их вылечить, для каждого было описание в официальной документации.

  • При желании к мобильному приложению на maui можно прикрутить любые нативные библиотеки.

  • При создании биндингов для классов на Котлин иногда встречаются нюансы, но это уже тема отдельной статьи. С пушами получилось всё стандартно.

  • С релизом .Net 9 биндинги для нативных библиотек для андроида стало делать сильно проще. Даже для таких больших как rustore push или rustore pay


    Ссылка на репозиторий: тынц

    Рядом с итоговым репозиторием лежат репозитории разной степени готовности. Например, rustore pay уже видит добавленные в интерфейсе Rustore покупки, Remote Config - видит конфиги на сервере, а Ok.Tracer - шлёт крэши и показывает их в Web интерфейсе.

    Буду рад вашим пул реквестам, вопросам и комментариям.

Комментарии (0)