Forum Xamarin.Forms

Beacon and Dependency

HatimNourbayHatimNourbay FRMember
edited June 2015 in Xamarin.Forms

Hello!

I have been using the AltBeacon library to find some beacons I just bought. I have largely been re-using the code of @chrisriesgo (many thanks to him by the way).
What I am trying to pull here is a little bit different from what he does however. I do not want to call the service on the main page, but when I navigate to a certain ContentPage. But when I launch my app and the service, the app crashes directly and I get an Unhandled Exception.
Here is my piece of Dependency code :

`[assembly: Xamarin.Forms.Dependency(typeof(BeaconClassDroid))]

namespace Mapstest.Droid
{

public class BeaconClassDroid : Java.Lang.Object, BeaconInterface
{

    public event EventHandler<ListChangedEventArgs> ListChanged;
    BeaconManager _iBeaconManager;
    RangeNotifier _rangeNotifier;
    Region _rangingRegion;
    Context context;
    List<Beacon> beacons;

    public BeaconClassDroid ()
    {
        beacons = new List<Beacon> ();

        context = Forms.Context;
        _rangeNotifier = new RangeNotifier ();


    }

    public BeaconManager BeaconManagerImpl
    {
        get
        {
            if (_iBeaconManager == null)
            {
                _iBeaconManager = InitializeBeaconManager();
            }
            return _iBeaconManager;
        }
    }

    public void InitializeService()
    {
        _iBeaconManager = InitializeBeaconManager();
    }

    private BeaconManager InitializeBeaconManager()
    {
        BeaconManager bm = BeaconManager.GetInstanceForApplication(Forms.Context);
        bm.BeaconParsers.Add(new BeaconParser().SetBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));

        _rangingRegion = new Region("HelloBeacon", null, null, null);
        _rangeNotifier.DidRangeBeaconsInRegionComplete += RangingBeaconsInRegion;
        bm.Bind((IBeaconConsumer)Forms.Context);
        return bm;

    }


    public void StartRanging()
    {
        BeaconManagerImpl.SetForegroundBetweenScanPeriod(5000); // 5000 milliseconds

        BeaconManagerImpl.SetRangeNotifier(_rangeNotifier);
        _iBeaconManager.StartRangingBeaconsInRegion(_rangingRegion);
    }


    public void RangingBeaconsInRegion(object sender, RangeEventArgs e)
    {
        if (e.Beacons.Count > 0)
        {
            foreach (var b in e.Beacons)
            {
                beacons.Add(b);

            }
        }
    }`

And my Content Page code :

`public class AboutPage : ContentPage
{
public List Data { get; set; }

    public event EventHandler ListChanged;

    public AboutPage ()
    {
        Title = "About";
        Icon = "about.png";
        DependencyService.Get<BeaconInterface>().StartRanging();

        var button = new Button
        {
            Text = "Testing",
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };
        var stop = new Button
        {
            Text = "Stop",
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };


    bool timerStatus = false;

        button.Clicked += delegate
        {
            timerStatus = true;
            Device.StartTimer (new TimeSpan (0,0,6), () =>{
                if (timerStatus)
                {
                    DependencyService.Get<BeaconInterface>().InitializeService();
                    /*if (Data.Count != 0)
                    {
                        moi.Text = Data[0].Id;
                    }
                    else
                    {
                        moi.Text = "You failed!";
                    }*/
                }
                return timerStatus;
            });
        };

        stop.Clicked += delegate
        {
            timerStatus = false;
        };`

I am only trying to locate the beacons in the room, not monitor them.
Also, my use permissions are correct (I think) :
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> <uses-feature android:name="android.hardware.bluetooth" android:required="true"/>

I would really appreciate any kind of help, I am really drowning :/
Thank you!

Posts

  • chris_riesgochris_riesgo USUniversity ✭✭✭

    @HatimNourbay - Thanks for the shout out. Sorry to hear you're having some trouble. Have you looked at my XForms sample on GitHub?

  • HatimNourbayHatimNourbay FRMember

    @chris_riesgo Hello, thank you for your time.
    Indeed, it is your code I have been mostly using.
    I did not display all the code on the page as I thought it would be irrelevant. I have successfully created the RangeNotifier class and the BeaconInterface.
    The issue (if I have correctly grasped the notions of beacons) is that I want to start the ranging when the ContentPage starts, not on the main page.

    Thus, I have called the StartRanging() at the beginning of the the contentpage, and I wanted the beacons to be added to the List and the data transfered to List whenever I click on a button, and only then. So inside the Button Delegate, I have called InitializeService()
    I may have been doing something wrong, but I do not know where.

  • chris_riesgochris_riesgo USUniversity ✭✭✭
    edited June 2015

    @HatimNourbay - I'm doing most of this from memory and from looking back over my code. Hopefully it is helpful.

    1. Take a look at the MainActivity.cs in my Forms example. You must have a class that implements IBeaconConsumer for the Beacon callback system to work, and I believe that the object that implements that interface must be an Android Context type class (like Activity). The callback into OnBeaconServiceConnect should only happen once. Once this method has been hit, that's the trigger to know that the underlying beacon service is ready to go to work. You can't call StartRanging or StartMonitoring until then.

    2. In your AboutPage class, you're calling StartRanging and InitializeService in opposite spots. You should call InitializeService during your page construction or in the OnAppearing method. This will fire up the beacon system (and hopefully trigger the OnBeaconServiceConnect callback). Then, call StartRanging in your button click handler when you're ready to start actually looking for beacons. Don't forger: you can't call StartRanging until the callback to OnBeaconServiceConnect on the Activity has happened, or you'll likely receive errors.

    Does that help?

  • HatimNourbayHatimNourbay FRMember

    I still have some value transfer problem I think, but I get the general calling idea, and this is what I was searching for. Thank you very much.
    I will post my final results if get this to work properly.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @HatimNourbay have you find a solution to use @chris_riesgo Library in Xamarin Forms?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    @chris_riesgo have you an example for Monitoring beacons enter and exit region? your XF example seems to be only a Ranging demo

Sign In or Register to comment.