错误:无法激活 JNI 句柄 – Xamarin 中的 WorkManager 实现

huangapple go评论69阅读模式
英文:

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

问题

我一直在尝试在.NET中使用Xamarin实现WorkManager (https://developer.android.com/topic/libraries/architecture/workmanager/),以迁移旧代码,其中我们使用了jobscheduler。在启动应用程序时,我收到了一个错误消息:"Error: Could not activate JNI Handle of type MyWorker1",但似乎无法弄清楚为什么我的实现出了问题。

我的基本实现:

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();
    }
}

JNI错误引用的类:

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();
        }

    }
}

希望这能帮助你解决问题。

英文:

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&lt;MyService1&gt;();
            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();
        }

    }
}

答案1

得分: 2

我找到了答案。 Proguard/R8 搞乱了 JNI 链接,因此添加一个自定义的 Proguard 配置文件(https://learn.microsoft.com/en-us/xamarin/android/deploy-test/release-prep/proguard?tabs=windows#customizing-proguard)只包含以下行:

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

解决了我的问题!原来我们指望默认配置来完成我们需要的工作,但它没有更新以处理 androidx(我不确定第二行是否需要,但对我们的用途不会有害)。

英文:

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)

huangapple
  • 本文由 发表于 2023年7月7日 02:47:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定