在Xamarin中使用AltBeacon

本文关键字:AltBeacon Xamarin | 更新日期: 2023-09-27 18:05:10

我希望有人能指导我这个问题。我正在尝试使用AltBeaconOrg,一个为Xamarin创建的开源Android iBeacon包装器。

我面临的问题是,当侦听器在服务中实现时,它工作得很好。

    [Service]
[IntentFilter(new [] {"com.testapp.SensorService"})]
public class DroidSensorService : Service, IRangeNotifier, IBeaconConsumer
{
    static readonly string Tag = typeof(DroidSensorService).Name;
    private IBinder binder;
    private Region _region;
    private BeaconManager _beaconManager;
    public DroidSensorService()
    {
    }
    public override void OnCreate()
    {
        base.OnCreate();
        Log.Debug(Tag, "OnCreate called in the Service");
    }
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug(Tag, "Service started");
        _beaconManager = BeaconManager.GetInstanceForApplication(ApplicationContext);
        _beaconManager.Bind(this);
        return StartCommandResult.Sticky;
    }
    public override IBinder OnBind(Intent intent)
    {
        binder = new DroidSensorServiceBinder(this);
        return binder;
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
        Log.Debug(Tag, "Service has been terminated");
    }
    public void OnBeaconServiceConnect()
    {
        _beaconManager.SetForegroundBetweenScanPeriod(5000);
        _beaconManager.SetRangeNotifier(this);
        _region = new AltBeaconOrg.BoundBeacon.Region("Region", null, null, null);
        _beaconManager.StartRangingBeaconsInRegion(_region);
    }
    public void DidRangeBeaconsInRegion(ICollection<Beacon> beacons, Region region)
    {
    }
}

当发现新的信标时,会引发DidRangeBeacons事件。

如果我使用一个类来包装信标代码来实现解决方案,例如:

[Service]
[IntentFilter(new [] {"com.testapp.SensorService"})]
public class DroidSensorService : Service, ISensorService
{
    static readonly string Tag = typeof(DroidSensorService).Name;
    private IBinder binder;
    private MyBeaconClass _myBeaconClass;
    public DroidSensorService()
    {
        _myBeaconClass = new MyBeaconClass(this);
    }
    public override void OnCreate()
    {
        base.OnCreate();
        Log.Debug(Tag, "OnCreate called in the Service");
    }
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Log.Debug(Tag, "Service started");
        _myBeaconClass.Start();
        return StartCommandResult.Sticky;
    }
    public override IBinder OnBind(Intent intent)
    {
        binder = new DroidSensorServiceBinder(this);
        return binder;
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
        Log.Debug(Tag, "Sensor Service has been terminated");
    }
}
public class MyBeaconClass : IRangeNotifier, IBeaconConsumer
{
    private Context _context;
    private Region _region;
    private BeaconManager _beaconManager;
    public MyBeaconClass(Context context)
    {
        _context = context;
    }
    public Context ApplicationContext
    {
        get
        {
            return _context.ApplicationContext;
        }
    }
    public IntPtr Handle
    {
        get
        {
            return _context.Handle;
        }
    }
    public void Start()
    {
        _beaconManager = BeaconManager.GetInstanceForApplication(_context.ApplicationContext);
        _beaconManager.Bind(this);
    }
    public void OnBeaconServiceConnect()
    {
        _beaconManager.SetForegroundBetweenScanPeriod(5000);
        _beaconManager.SetRangeNotifier(this);
        _region = new AltBeaconOrg.BoundBeacon.Region("Region", null, null, null);
        _beaconManager.StartRangingBeaconsInRegion(_region);
    }
    public void DidRangeBeaconsInRegion(ICollection<Beacon> beacons, Region region)
    {
    }
    public bool BindService(Intent intent, IServiceConnection serviceConnection, [GeneratedEnum] Bind flags)
    {
        return _context.BindService(intent, serviceConnection, flags);
    }
    public void UnbindService(IServiceConnection serviceConnection)
    {
        _context.UnbindService(serviceConnection);
    }
    public void Dispose()
    {
    }
}

我得到以下错误:

无法激活Java类型'md53c8887b34fc5ad8a1fb3519f652d3fea/DroidSensorService'的JNI Handle 0x7fefabe700 (key_handle 0x11c1ff5)作为托管类型'Sensors.Droid.Classes.DroidSensorService'.

在Java.Interop.TypeManager

。n_Activate (IntPtr jnienv, IntPtr jclass, IntPtr typename_ptr, IntPtr signature_ptr, IntPtr jobject, IntPtr parameters_ptr) [0x00180] in/Users/builder/data/lanes/3540/1cf254db/source/monodroid/src/Mono.Android/src/Java.Interop/TypeManager.cs:176at(包装器动态方法)系统。对象:ac4a9174 - 05 - aa - 4926 - 9 - a80 - 8 a8455916649 (intptr、intptr intptr, intptr, intptr, intptr)

内部异常类似于"尝试调用虚拟方法'android.content.Context…"(Xamarin Studio把它剪掉了)

如果我把实例化MyBeaconClass的行移到Start()调用的上面,手机上的应用程序就会崩溃,Xamarin Studio也不会引发异常。

我很欣赏这段代码的目的是直接在Activity或Service类中工作,但如果我能够实现这一点,那将会整洁得多,因为我将与其他功能共享这个服务。

注意:我已经尝试使用直接注入的上下文和Android.App.Application.Context。

非常感谢您的阅读。理查德。

在Xamarin中使用AltBeacon

您的MyBeaconClass必须从Java.Lang.Object继承,以便由Xamarin.Android创建JNI包装器,以便Java调用被封送到c#。请记住,您正在处理两个必须桥接的vm:

public class MyBeaconClass : Java.Lang.Object, IRangeNotifier, IBeaconConsumer
{
   ~~~
}

谢谢你的回答SushiHangover。遗憾的是,你的建议不是这个问题的答案,至少不是唯一的答案。最后,我在一个服务类中实现了解决方案,并从第一个服务类中调用新服务。

谢谢,理查德