Xamarin.Android上的服务是在一个单独的过程中启动的。该服务实现了AltBeacon v2.12库。 DidRangeBeaconsInRegion回调方法在RangeNotifier对象中不起作用。 在开始测量双子(方法StartRangingBeaconsInRegion(区域))之后,信标不会被确定。
代码:
服务定义:
[Service(Name = SERVICE_NAME, Process = ":myProcess", Enabled = true, Exported = false, IsolatedProcess = false)]
配置BeaconManager(在服务中定义)
beaconManager = BeaconManager.
GetInstanceForApplication(DroidApplication.Current);
rangeNotifier = new RangeNotifier();
beaconManager.ForegroundBetweenScanPeriod = 1000;
beaconManager.ForegroundScanPeriod = 1000;
beaconManager.BackgroundMode = false;
var beaconParser = new BeaconParser();
beaconParser.SetBeaconLayout("...");
beaconManager.BeaconParsers.Add(beaconParser);
beaconManager.AddRangeNotifier(rangeNotifier);
beaconManager.ApplySettings();
3.服务代码:
public class BeaconService:Service,IBeaconConsumer
...
{
private async void DoWork()
{
while (true)
{
try
{
lg.Error("DOWORK");
beaconManager.Bind(this);
await Task.Delay(5000);
beaconManager.Unbind(this);
}
catch (Exception ex)
{
}
}
}
public bool BindService(Intent p0, IServiceConnection p1, int p2)
{
return this.BindService(p0, p1,Bind.AutoCreate);
}
public void OnBeaconServiceConnect()
{
string[] guids = { "....","...." };
foreach (var region in beaconManager.RangedRegions.ToList())
beaconManager.StopRangingBeaconsInRegion(region);
for (int i = 0; i < guids.Length; i++)
{
var uuid = Identifier.Parse(guids[i]);
var region = new Region("R" + i, uuid, null, null);
beaconManager.StartRangingBeaconsInRegion(region);
}
}
private class RangeNotifier
{
//This method doesn't invoke
public void DidRangeBeaconsInRegion(ICollection<Beacon> beacons, Region region)
{
Logger lg = LogManager.GetCurrentClassLogger();
lg.Debug(String.Format("COUNT -{0}",beacons.Count));
}
}
}
我没有调用BeaconManager.IsMainProcess,因为BeaconManager的定义和配置发生在服务本身,它在另一个进程中启动。
按日志显示扫描在主进程中有效。如果我在一个单独的流程中启动服务,这怎么可能呢? BaconManager对象和BaconManager启动的配置直接在服务中进行。绑定也发生在服务中。 enter image description here
在这种情况下是否可以在我的示例中定义类的属性中的服务设置,或者我是否需要在应用程序清单中注册它们?
我的清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="myPackageApp" android:versionCode="4" android:versionName="0.12.3" android:installLocation="auto">
<uses-sdk android:minSdkVersion="18" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.location.network" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="myapp.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<permission android:name="myApp.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
<application android:label="@string/gen_application_name" android:icon="@mipmap/ic_launcher" android:largeHeap="true">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="..." />
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
</application>
有什么想法吗?谢谢。
答案 0 :(得分:0)
当您在Android Studio中使用Java完成所有工作并且只有一个主应用程序进程时,在不同的进程中运行库的扫描服务是非常棘手的。将Xamarin扔进混合物中,然后添加一个现有的独立过程,你真的为你做了工作!也就是说,这里有一些可能有用的提示:
当服务A处于单独的流程中时,当您使用服务A启动服务B时,我不是关于Android上发生的事情的专家。也许Android会在主进程中启动服务B,除非你另外配置它。
尝试从单独的进程中禁用信标扫描服务。如果您发现扫描服务仍在主进程中运行,那么该进程中的某些内容必须调用bind()或使用RegionBootstrap(内部调用bind())来启动它。如果您使用的是第三方库,则可能位于该库中。
请注意,库本身有自己的清单,因此其条目可能会与您的清单合并。检查是否存在包含更多元素的生成清单。
我不熟悉以第一个问题中描述的方式定义服务参数,所以我不能说它是否会引起麻烦。
我认为没有理由定义BeaconIntentProcessor。图书馆应该为你做这件事。
应该可以从服务,活动或应用程序类开始扫描。在OnBeaconServiceConnect()
定义中设置断点或日志行,并确保它被调用。如果是这样,您就正确启动了服务,并且已正确实例化了BeaconManager
。
编辑:根据评论中的讨论,似乎关键问题是调用beaconManager.AddRangeNotifier(rangeNotifier);
的位置。必须在预期接收回调的过程中调用此方法。虽然BeaconManager
是单例,但在Android(以及所有Linux)多进程应用程序中,每个进程都有一个单例的副本。
因此,如果您在BeaconManager
的后台流程实例上添加通知程序,那么将收到回调。如果要在主UI进程上接收回调,则必须从该进程中存在的BeaconManager
实例设置通知程序。