You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin实现WorkManager遇JNI句柄激活失败问题求助

问题:Xamarin中移植WorkManager触发JNI激活错误

将原有JobScheduler代码移植到Xamarin的AndroidX.Work环境时,应用启动出现错误:Error: Could not activate JNI Handle of type MyWorker1,无法定位问题根源。

基础抽象Worker实现代码

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

MyWorker1实现代码

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. 添加Preserve特性防止链接器移除类型

Xamarin的链接器会在发布模式下移除未被直接引用的类型/成员,WorkManager通过反射实例化Worker,很容易被误删。给所有Worker类及依赖的服务添加[Android.Runtime.Preserve(AllMembers = true)]特性:

using Android.Runtime;

[Preserve(AllMembers = true)]
public abstract class BackgroundWorkerBase : Worker
{
    // ... 原有代码
}

[Preserve(AllMembers = true)]
public class MyWorker1: BackgroundWorkerBase
{
    // ... 原有代码
}

// 对MyService1也添加该特性
[Preserve(AllMembers = true)]
public class MyService1
{
    // ... 服务代码
}

2. 移除Worker构造中的Xamarin.Forms初始化

WorkManager的Worker运行在后台线程/独立进程中,不适合初始化Xamarin.Forms。Forms初始化应放在应用启动的UI线程(如MainActivity的OnCreate方法),Worker中仅依赖已初始化的服务:

protected BackgroundWorkerBase(Context context, WorkerParameters workerParameters) : base(context, workerParameters)
{
    // 移除Forms.Init代码
    if (!ViewModelLocator.IsRegistered)
        ViewModelLocator.RegisterDependencies(Helpers.Settings.UseMocks);
    MyService = ViewModelLocator.Resolve<MyService1>();
    WorkerParameters = workerParameters;
}

3. 确保Worker构造函数签名正确

WorkManager要求Worker必须有public的构造函数,参数为Context和WorkerParameters,你的代码中已满足,但需确认未被链接器修改。

4. 检查链接器配置(可选)

如果添加Preserve特性无效,可在Android项目的Linker.xml中显式保留相关类型:

<linker>
  <assembly fullname="MyTooling">
    <type fullname="MyTooling.Droid.Workers.BackgroundWorkerBase" preserve="all" />
    <type fullname="MyTooling.Droid.Workers.MyWorker1" preserve="all" />
    <type fullname="MyTooling.Services.MyService1" preserve="all" />
  </assembly>
</linker>

内容的提问来源于stack exchange,提问作者Ace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:03:25