Search code examples
c#xamarinandroid-workmanager

Error: Could not activate JNI Handle - WorkManager implementation in Xamarin


I've been trying to implement the WorkManager (https://developer.android.com/topic/libraries/architecture/workmanager/) in .NET using Xamarin (porting old code where we used jobscheduler). On booting up the app, I get an "Error: Could not activate JNI Handle of type MyWorker1", and can't seem to figure out why my implementation is broken.

My base implementation:


using Android.App;
using Android.Content;
using AndroidX.Work;
using System;
using MyTooling.Services;
using MyTooling.ViewModels.Base;

namespace MyTooling.Droid.Workers
{
    public abstract class BackgroundWorkerBase : Worker
    {
        protected MyService1 MyService;

        protected WorkerParameters WorkerParameters { get; }

        protected BackgroundWorkerBase(Context context, WorkerParameters workerParameters) : base(context, workerParameters)
        {
            if (!Xamarin.Forms.Forms.IsInitialized)
                Xamarin.Forms.Forms.Init(Application.Context, null);
            if (!ViewModelLocator.IsRegistered)
                ViewModelLocator.RegisterDependencies(Helpers.Settings.UseMocks);
            MyService = ViewModelLocator.Resolve<MyService1>();
            WorkerParameters = workerParameters;
               
        }
        public override Result DoWork()
        {
            try
            {
                var success = TryBackgroundWork();
                if (!success || AnyWorkLeft())
                    return Result.InvokeRetry();
                else
                    return Result.InvokeSuccess();
            }
            catch (Exception ex)
            {
                Log.LogError(ex);
                return Result.InvokeFailure();
            }
        }

        protected abstract bool AnyWorkLeft();
        protected abstract bool TryBackgroundWork();
    }
}

The class that the JNI error is referring to:

using Android.Content;
using AndroidX.Work;

namespace MyTooling.Droid.Workers
{
    public class MyWorker1: BackgroundWorkerBase
    {
        public MyWorker1(Context context, WorkerParameters workerParameters) : base(context, workerParameters)
        {
        }

        protected override bool AnyWorkLeft()
        {
            return MyService.AnyWork1Left();
        }

        protected override bool TryBackgroundWork()
        {
            return MyService.TryDoWork1();
        }

    }
}

Solution

  • I figured out the answer. Proguard/R8 was messing up the JNI linking, so adding a custom proguard configuration file (https://learn.microsoft.com/en-us/xamarin/android/deploy-test/release-prep/proguard?tabs=windows#customizing-proguard) consisting only of the following lines:

    -keep class androidx.** {*;}
    -keep class android.arch.** {*;}
    

    fixed my issue! Turns out we were counting on the default config to do what we needed, and it hadn't been updated to deal with androidx (I am not sure that the second line there is needed, but it won't hurt for our uses)

    EDIT: This only partially fixed the issue. We are still intermittently running into this issue, even with a fixed proguard file.