在另一个进程中启动AltBeacon

时间:2018-01-25 17:25:55

标签: android xamarin process altbeacon

Xamarin.Android上的服务是在一个单独的过程中启动的。该服务实现了AltBeacon v2.12库。 DidRangeBeaconsInRegion回调方法在RangeNotifier对象中不起作用。 在开始测量双子(方法StartRangingBeaconsInRegion(区域))之后,信标不会被确定。

代码:

  1. 服务定义:

    [Service(Name = SERVICE_NAME, Process = ":myProcess", Enabled = true, Exported = false, IsolatedProcess = false)]

  2. 配置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. 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的定义和配置发生在服务本身,它在另一个进程中启动。

    1. 按日志显示扫描在主进程中有效。如果我在一个单独的流程中启动服务,这怎么可能呢? BaconManager对象和BaconManager启动的配置直接在服务中进行。绑定也发生在服务中。 enter image description here

    2. 在这种情况下是否可以在我的示例中定义类的属性中的服务设置,或者我是否需要在应用程序清单中注册它们?

    3. 我是否需要定义BeaconIntentProcessor?
    4. 我怀疑我没有正确定义 - beaconManager = BeaconManager.GetInstanceForApplication(DroidApplication.Current);
    5. 如何正确启动扫描?从主应用程序进程(例如,来自激活或来自自定义DroidApplication类)还是可以从服务进行?
    6. 我的清单文件:

       <?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>
      

      有什么想法吗?谢谢。

1 个答案:

答案 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实例设置通知程序。