iOS Tutorial Geofence - Monitoring a region

Discussion in 'iOS Tutorials' started by Erel, Jul 10, 2017.

Thread Status:
Not open for further replies.
  1. Erel

    Erel Administrator Staff Member Licensed User

    This example extends iLocation library to allow monitoring regions in the background.

    The code is pretty simple. You first need to create a circular region which you want to track and then call MonitorRegion to start tracking it.

    The RegionEnter / RegionExit events will be raised, even if the app is in the background.
    The StateChanged event is called once after each call to MonitorRegion.

    A few notes:
    - The minimum radius is 100 meters. The OS uses less accurate means to determine the location so it is not very accurate. You can start another app that uses the GPS while testing it.
    - The example tracks a single region. You can track up to 20 regions.
    - Don't kill the app with a swipe as it will prevent it from being started.
    - Run your app in release mode if you want to test the background behavior. It should show a notification when the app is in the background and it detects a state change.
    - No special background mode is required.
     

    Attached Files:

    BillMeyer and JanPRO like this.
  2. Christian García S.

    Christian García S. Active Member Licensed User

    Thanks Erel, it is a great contribution.

    I have a question, can this function coexist with ebeacon monitoring region ?? https://www.b4x.com/android/forum/threads/ibeacons.79257/

    I saw that you have replaced in the function of ebeacon, this:

    NSLog (@ "Enter");
    NSLog (@ "Exit");

    with this new functions:

    _regionexit
    _regionenter

    As I can differentiate what type of region is entering, circulate region or ebeacon region so that it does not release the same message ???

    If I put some code in LocManager_StateChanged for ebeacon region and circular region I can't differentiate which region is, or I must put code in LocManager_RegionEnter and differentiate with other variable ??

    Thanks,

    Regards,
    Christian
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    It should be possible to combine both solutions. Please upload your combined project.
     
  4. Christian García S.

    Christian García S. Active Member Licensed User

    Thanks Erel, attached the project.

    I am trying to combine but I receive the same notification when enter to Circular or Beacon region.

    Maybe can we distinguish with value from identifier:

    Start monitoring: CLBeaconRegion (identifier:'monitor', uuid:AEA51B96-3199-11E7-93AE-92361F002671, major: (null), minor: (null))
    Start monitoring: CLCircularRegion (identifier:'region2', center:<-0.18291040,-78.47987960>, radius:100.00m)

    For example I would need put a code like that in LocManager_RegionEnter:

    Code:
    If identifier = "BeaconRegion" Then
            ShowNotification(
    "Exclusive content for you")
    Else If identifier = "CircularRegion" Then
            ShowNotification(
    "Welcome to store open your APP")
    End If
    In this documentation you can see the following: https://developer.apple.com/documen...ng_the_user_s_proximity_to_geographic_regions

    upload_2017-9-13_13-22-2.png

    Thanks for your help.

    Regards,
    Christian
     

    Attached Files:

  5. Erel

    Erel Administrator Staff Member Licensed User

    Does this work:
    Code:
    Log(Region.GetField("identifier"))
    ?

    You can also distinguish between the different types by checking the region type:
    Code:
    Log(GetType(Region))
     
  6. Christian García S.

    Christian García S. Active Member Licensed User

    Thanks Erel for your reply, after I maked some tests I have these conclusions:
    • When I test separately (different apps) with same code, region enter and exit for Beacon and Circular region works.
    • When I test together (Region for Beacons and Circular same app), region enter and exit doesn't raise.
    • When I test together, event StateChanged raise some times but I don't know how I recognize which region is, and I want take control about this notifications.
    This is the code:

    Code:
    #if objc
    - (NSObject*)createCircularRegdion:(double)lat :(double)lon :(double)radius :(NSString*)identifier {
        return [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(lat, lon) radius:(CLLocationDistance)radius identifier:identifier];
    }
    @end
    @interface B4ILocationManager (beacon)
    @end

    @implementation B4ILocationManager (beacon)

    - (void)locationManager:(CLLocationManager *)manager
            didRangeBeacons:(NSArray*)beacons
                   inRegion:(CLBeaconRegion *)region {
                  if (beacons.count > 0) {
                    [B4IObjectWrapper raiseEvent:self :@"_didrangebeacons:"
                        :@[[B4IObjectWrapper createWrapper:[B4IList new] object:beacons]]];
                    }
        }

    - (void)locationManager:(CLLocationManager *)manager
              didExitRegion:(CLRegion *)region {
              [B4IObjectWrapper raiseEvent:self :@"_regionexit:" :@[region]];
        }
    - (void)locationManager:(CLLocationManager *)manager
             didEnterRegion:(CLRegion *)region {
             [B4IObjectWrapper raiseEvent:self :@"_regionenter:" :@[region]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    monitoringDidFailForRegion:(CLRegion *)region
                  withError:(NSError *)error {
        NSLog(@"Error: %@", error);
        [B4IObjectWrapper raiseEvent:self :@"_statechanged:" :@[@(3)]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    didStartMonitoringForRegion:(CLRegion *)region {
        NSLog(@"Start monitoring: %@", region);
    }
    - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)State forRegion:(CLRegion *)region {
       NSLog(@"didDetermineState: %@", @(State));
       [B4IObjectWrapper raiseEvent:self :@"_statechanged:" :@[@(State)]];
    }
    #End If
    Can you add other parameter to StateChanged like this from objc:

    Code:
    Sub LocManager_StateChanged(State As Int, Region As NativeObject)
    I was trying change in code below, but I don't know how, I has many erros:

    Code:
    - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)State forRegion:(CLRegion *)region {
       NSLog(@
    "didDetermineState: %@", @(State));
       [B4IObjectWrapper raiseEvent:self :@
    "_statechanged:" :@[@(State)]];
    }
    Please you can make some test or changes to these functions that can works together.

    Thanks in advance,

    Regards,

    Christian
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    The event sub signature should be:
    Code:
    Sub LocManager_StateChanged(State As Int, Region As Object)
    OBJC Code:
    Code:
    #if objc
    - (NSObject*)createCircularRegdion:(double)lat :(double)lon :(double)radius :(NSString*)identifier {
       return [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(lat, lon) radius:(CLLocationDistance)radius identifier:identifier];
    }
    @end
    @interface B4ILocationManager (beacon)
    @end

    @implementation B4ILocationManager (beacon)

    - (void)locationManager:(CLLocationManager *)manager
      didExitRegion:(CLRegion *)region {
          [B4IObjectWrapper raiseEvent:self :@"_regionexit:" :@[region]];
       }
    - (void)locationManager:(CLLocationManager *)manager
      didEnterRegion:(CLRegion *)region {
          [B4IObjectWrapper raiseEvent:self :@"_regionenter:" :@[region]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    monitoringDidFailForRegion:(CLRegion *)region
      withError:(NSError *)error {
       NSLog(@"Error: %@", error);
       [B4IObjectWrapper raiseEvent:self :@"_statechanged:" :@[@(3), region]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    didStartMonitoringForRegion:(CLRegion *)region {
       NSLog(@"Start monitoring: %@", region);
    }
    - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)State forRegion:(CLRegion *)region {
      NSLog(@"didDetermineState: %@", @(State));
      [B4IObjectWrapper raiseEvent:self :@"_statechanged::" :@[@(State), region]];
    }
    #End If
     
  8. Christian García S.

    Christian García S. Active Member Licensed User

    Hello @Erel

    When I tried this:
    I get:

    upload_2019-3-29_12-32-11.png

    How I can do ? I have B4i 5.51.

    Thanks
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    Download the example from the first post and run it without making any changes. Do you get this error?

    If you made changes then you should explain which changes you made.
     
  10. Christian García S.

    Christian García S. Active Member Licensed User

    I changed code to for monitoring beacons and circular regions:
    I explained from post 2 to 7.

    Log convert Region.GetField("identifier") to string, but When I want use with a variable string I have this error.

    The complete code is:

    Code:
    #if objc
    - (NSObject*)createCircularRegdion:(double)lat :(double)lon :(double)radius :(NSString*)identifier {
       return [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(lat, lon) radius:(CLLocationDistance)radius identifier:identifier];
    }
    @end
    @interface B4ILocationManager (beacon)
    @end

    @implementation B4ILocationManager (beacon)
    - (void)locationManager:(CLLocationManager *)manager
            didRangeBeacons:(NSArray*)beacons
                   inRegion:(CLBeaconRegion *)region {
                  if (beacons.count > 0) {
                    [B4IObjectWrapper raiseEvent:self :@"_didrangebeacons:"
                        :@[[B4IObjectWrapper createWrapper:[B4IList new] object:beacons]]];
                    }
        }
    - (void)locationManager:(CLLocationManager *)manager
      didExitRegion:(CLRegion *)region {
          [B4IObjectWrapper raiseEvent:self :@"_regionexit:" :@[region]];
       }
    - (void)locationManager:(CLLocationManager *)manager
      didEnterRegion:(CLRegion *)region {
          [B4IObjectWrapper raiseEvent:self :@"_regionenter:" :@[region]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    monitoringDidFailForRegion:(CLRegion *)region
      withError:(NSError *)error {
       NSLog(@"Error: %@", error);
       [B4IObjectWrapper raiseEvent:self :@"_statechanged:" :@[@(3), region]];
    }
    - (void)locationManager:(CLLocationManager *)manager
    didStartMonitoringForRegion:(CLRegion *)region {
       NSLog(@"Start monitoring: %@", region);
    }
    - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)State forRegion:(CLRegion *)region {
      NSLog(@"didDetermineState: %@", @(State));
      [B4IObjectWrapper raiseEvent:self :@"_statechanged::" :@[@(State), region]];
    }
    #End If
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    The previous post was from 2017. You should start a new thread and provide all information.
     
Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice