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
相关产品推荐
相关产品推荐

