Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/crossgeeks/geofenceplugin
Geofence Plugin for Xamarin iOS and Android
https://github.com/crossgeeks/geofenceplugin
Last synced: about 1 month ago
JSON representation
Geofence Plugin for Xamarin iOS and Android
- Host: GitHub
- URL: https://github.com/crossgeeks/geofenceplugin
- Owner: CrossGeeks
- License: mit
- Created: 2017-07-21T20:09:29.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2022-08-25T20:20:05.000Z (over 2 years ago)
- Last Synced: 2024-10-05T20:17:47.844Z (3 months ago)
- Language: C#
- Homepage:
- Size: 354 KB
- Stars: 48
- Watchers: 7
- Forks: 22
- Open Issues: 26
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
## Geofence Plugin for Xamarin
Simple cross platform plugin to handle geofence events such as entering, leaving and staying in a geofence region.
### Setup
* Available on NuGet: http://www.nuget.org/packages/Plugin.Geofence [![NuGet](https://img.shields.io/nuget/v/Plugin.Geofence.svg?label=NuGet)](https://www.nuget.org/packages/Plugin.Geofence/)
* Install into your PCL project and Client projects.**Supports**
* Xamarin.iOS
* Xamarin.Android### TODO
* Include UWP support
* Region expiration time support
* Refactor error handling (Error codes)
* Implement an Android Location Service for location updates
* Geofence general settings configuration support
* Android support for more than 100 geofence regions### API Usage
Call **CrossGeofence.Current** from any project or PCL to gain access to APIs. Must initialize plugin on each platform before use. Should only be used after initialization, if not will get GeofenceNotInitializedException.
**CrossGeofence.Initialize<'T'>**
This methods initializes geofence plugin. The generic T should be a class that implements IGeofenceListener. This will be the class were you would listen to all geofence events.#### iOS
On the AppDelegate:
```csharp
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
//Initialization...
CrossGeofence.Initialize ();return base.FinishedLaunching (app, options);
}
```#### Android
Create an Geofence service class to be able to handle geofence events even when application is closed.
```csharp
[Service]
public class GeofenceService : Service
{
public override void OnCreate()
{
base.OnCreate();System.Diagnostics.Debug.WriteLine("Geofence Service - Created");
}public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
System.Diagnostics.Debug.WriteLine("Geofence Service - Started");
return StartCommandResult.Sticky;
}public override Android.OS.IBinder OnBind(Android.Content.Intent intent)
{
System.Diagnostics.Debug.WriteLine("Geofence Service - Binded");
return null;
}public override void OnDestroy()
{
System.Diagnostics.Debug.WriteLine("Geofence Service - Destroyed");
base.OnDestroy();
}
}
```Initialization on Application class.
```csharp
[Application]
public class GeofenceAppStarter : Application
{
public static Context AppContext;public GeofenceAppStarter(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{}
public override void OnCreate()
{
base.OnCreate();AppContext = this.ApplicationContext;
//TODO: Initialize CrossGeofence Plugin
//TODO: Specify the listener class implementing IGeofenceListener interface in the Initialize generic
//CrossGeofence.Initialize();
//CrossGeofence.GeofenceListener.OnAppStarted();
//Start a sticky service to keep receiving geofence events when app is closed.
StartService();
}public static void StartService()
{
AppContext.StartService(new Intent(AppContext, typeof(GeofenceService)));if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
{
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(GeofenceService)), 0);
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
alarm.Cancel(pintent);
}
}public static void StopService()
{
AppContext.StopService(new Intent(AppContext, typeof(GeofenceService)));
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
{
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(GeofenceService)), 0);
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
alarm.Cancel(pintent);
}
}}
```**IGeofenceListener implementation**
Must implement IGeofenceListener. This would be commonly implemented in the Core project if sharing code between Android or iOS. In the case you are using the plugin only for a specific platform this would be implemented in that platform.
```csharp
public class CrossGeofenceListener : IGeofenceListener
{
public void OnMonitoringStarted(string region)
{
Debug.WriteLine(string.Format("{0} - Monitoring started in region: {1}", CrossGeofence.Tag, region));
}public void OnMonitoringStopped()
{
Debug.WriteLine(string.Format("{0} - {1}", CrossGeofence.Tag, "Monitoring stopped for all regions"));
}public void OnMonitoringStopped(string identifier)
{
Debug.WriteLine(string.Format("{0} - {1}: {2}", CrossGeofence.Tag, "Monitoring stopped in region", identifier));
}public void OnError(string error)
{
Debug.WriteLine(string.Format("{0} - {1}: {2}", CrossGeofence.Tag, "Error", error));
}
// Note that you must call CrossGeofence.GeofenceListener.OnAppStarted() from your app when you want this method to run.
public void OnAppStarted()
{
Debug.WriteLine(string.Format("{0} - {1}", CrossGeofence.Tag, "App started"));
}public void OnRegionStateChanged(GeofenceResult result)
{
Debug.WriteLine(string.Format("{0} - {1}", CrossGeofence.Tag, result.ToString()));
}
}
```Enum of Geofence Transaction Types:
```csharp
///
/// GeofenceTransition enum
///
public enum GeofenceTransition
{
///
/// Entry transition
///
Entered,
///
/// Exit transition
///
Exited,
///
/// Stayed in transition
///
Stayed,
///
/// Unknown transition
///
Unknown
}
```
#### Geofence Circular Region Class - PropertiesClass to define and configure geofence region
```csharp
///
/// Region identifier
///
public string Id { get; set; }
///
/// Region center Latitude
///
public double Latitude { get; set; }
///
/// Region center Longitude
///
public double Longitude { get; set; }
///
/// Radius covered by the region in meters
///
public double Radius { get; set; }
///
/// Notify when enters region
///
public bool NotifyOnEntry { get; set; }
///
/// Notify when stays in region based on the time span specified in StayedInThresholdDuration
/// Note: Stayed in transition will not be fired if device has exit region before the StayedInThresholdDuration
///
public bool NotifyOnStay { get; set; }
///
/// Notify when exits region
///
public bool NotifyOnExit { get; set; }
///
/// Notitication message when enters region
///
public string NotificationEntryMessage { get; set; }
///
/// Notification message when exits region
///
public string NotificationExitMessage { get; set; }
///
/// Notification message when stays in region
///
public string NotificationStayMessage { get; set; }
///
/// Persist region so that is available after application closes
///
public bool Persistent { get; set; }
///
/// Enables showing local notifications. Defaults to showing all notifications, unless setting ShowEntry/Exit/StayNotification entries to false.
/// Messages could be configured using properties: NotificationEntryMessage, NotificationExitMessage, NotificationStayMessage
///
public bool ShowNotification { get; set; }
///
/// Enables showing local entry notifications. ShowNotification must be true.
/// Messages could be configured using properties: NotificationEntryMessage
///
public bool ShowEntryNotification { get; set; }
///
/// Enables showing local exit notifications. ShowNotification must be true.
/// Messages could be configured using properties: NotificationExitMessage
///
public bool ShowExitNotification { get; set; }
///
/// Enables showing local stay notifications. ShowNotification must be true.
/// Messages could be configured using properties: NotificationStayMessage
///
public bool ShowStayNotification { get; set; }
///
/// Sets minimum duration time span before passing to stayed in transition after an entry
///
public TimeSpan StayedInThresholdDuration;
```#### Geofence Result Class - Properties
When there is a geofence event update you will get an instance of this class.
```csharp
///
/// Last time entered the geofence region
///
public DateTime? LastEnterTime { get; set; }
///
/// Last time exited the geofence region
///
public DateTime? LastExitTime { get; set; }
///
/// Result transition type
///
public GeofenceTransition Transition { get; set; }
///
/// Region identifier
///
public string RegionId { get; set; }
///
/// Duration span between last exited and entred time
///
public TimeSpan? Duration { get { return LastExitTime - LastEnterTime; } }
///
/// Time span between the last entry and current time.
///
public TimeSpan? SinceLastEntry { get { return DateTime.Now - LastEnterTime; } }
///
/// Result latitude
///
public double Latitude { get; set; }
///
/// Result longitude
///
public double Longitude { get; set; }
///
/// Result accuracy
///
public double Accuracy { get; set; }
```#### **CrossGeofence.Current**
Methods and properties**StartMonitoring**
Start monitoring in specified region
```csharp
void StartMonitoring(GeofenceCircularRegion region);
```Starts monitoring multiple regions
```csharp
void StartMonitoring(IList regions);
```**StopMonitoring**
Stop monitoring specified geofence region.
```csharp
void StopMonitoring(GeofenceCircularRegion region);
```Stop monitoring multiple regions.
```csharp
void StopMonitoring(IList regions);
```**StopMonitoringAllRegions**
Stop monitoring all geofence regions.
```csharp
void StopMonitoringAllRegions();
```**IsLocationEnabled**
Determines whether location is enabled and returns the result to the specified action.
```csharp
void IsLocationEnabled(Action returnAction);
```**LastKnownLocation**
Last known geofence location. This location will be null if isn't monitoring any regions yet.
```csharp
GeofenceLocation LastKnownLocation { get; }
```**IsMonitoring**
Indicator that is true if at least one region is been monitored
```csharp
bool IsMonitoring { get; }
```**Regions**
Dictionary that contains all regions been monitored
```csharp
IReadOnlyDictionary Regions { get; }
```**GeofenceResults**
Dicitonary that contains all geofence results received
```csharp
IReadOnlyDictionary GeofenceResults { get; }
```
#### ExampleStart monitoring a region
```csharp
CrossGeofence.Current.StartMonitoring(new GeofenceCircularRegion ("My Region",18.4802878,-69.9469203,52220) {
//To get notified if user stays in region for at least 5 minutes
NotifyOnStay=true,
StayedInThresholdDuration=TimeSpan.FromMinutes(5)});
```
#### Notes##### CrossGeofence Features
This are special features you can enable or change values. By default plugin uses Balanced Power Priority.
```csharp
//Set the Priority for the Geofence Tracking Location Accuracy
public static GeofencePriority GeofencePriority { get; set; }//Set the smallest displacement should be done from current location before a location update
public static float SmallestDisplacement { get; set; }
/// Request the user for Notifications Permission. Set to false if this is already handled in the client application.
public static bool RequestNotificationPermission { get; set; }
/// Request the user for Location Services Permissions. Set to false if this is already handled in the client application.
public static bool RequestLocationPermission { get; set; }
```Geofence Accuracy Precision Priority enum
```csharp
///
/// Geofence Accuracy Precision Priority enum
///
public enum GeofencePriority
{
///
/// Sets the location updates for balanced power accurancy basing location on Cells and WiFi spots.
///
BalancedPower,
///
/// Highest accuracy uses GPS and other sources to determine best location precision
///
HighAccuracy,
///
/// Acceptable accuracy
///
AcceptableAccuracy,
///
/// Medium accuracy - Low Battery Usage
///
MediumAccuracy,
///
/// Low accuracy - Low Battery Usage
///
LowAccuracy,
///
/// Lowest Acurracy - No Power
///
LowestAccuracy
}
```##### Android Specifics
* Requires the following permissions:
* android.permission.ACCESS_FINE_LOCATION
* android.permission.ACCESS_COARSE_LOCATION
* com.google.android.providers.gsf.permission.READ_GSERVICES
* android.permission.RECEIVE_BOOT_COMPLETED. This permission allows the plugin to restore any geofence region previously monitored marked as persistent when rebooting.* There are a few things you can configure in Android project using the following properties from CrossGeofence class:
```csharp
//The sets the resource id for the icon will be used for the notification
public static int IconResource { get; set; }//The sets the sound uri will be used for the notification
public static Android.Net.Uri SoundUri { get; set; }
/// ARGB Color used for notification
public static int Color { get; set; }
/// Large icon resource used for notification
public static Android.Graphics.Bitmap LargeIconResource { get; set; }//Sets update interval for the location updates
public static int LocationUpdatesInterval { get; set; }//Sets fastest interval for the location updates
public static int FastestLocationUpdatesInterval { get; set; }
```* The package name of your Android aplication must start with lower case and shouldn't have any hyphen character or you will get the build error:
Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED
* Make sure you have updated your Android SDK Manager libraries:![image](https://cloud.githubusercontent.com/assets/2547751/6440604/1b0afb64-c0b5-11e4-93b8-c496e2bfa588.png)
##### iOS Specifics
* You need to do is to add the following key to your Info.plist file:
NSLocationAlwaysUsageDescription
You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the Info.plist file.
##### Important Notes
* The region monitoring feature of iOS only provides the possibility to monitor up to 20 regions at a time. Trying to monitor more than 20 regions will result in an error, indicating that the limit is crossed. See more at: [Reference](http://www.rapidvaluesolutions.com/tech_blog/geofencing-using-core-location-for-regional-monitoring-in-ios-applications/#sthash.AYIWNg19.dpuf). Actually this plugin handle this by only monitoring the 20 nearest regions when there is more than 20 regions been monitored by using significant location updates. [Need to add more than 20 regions](http://stackoverflow.com/questions/29654154/need-to-get-more-than-20-notification-for-region-monitoring/29703957#29703957)
* The region monitoring feature of Android has a limit of 100 regions per device user. Currently the plugin is not handling more than 100 regions on Android.#### Contributors
* [rdelrosario](https://github.com/rdelrosario)
* [aflorenzan](https://github.com/aflorenzan)
* [frankelydiaz](https://github.com/frankelydiaz)
* [jphbrivo](https://github.com/jphbrivo)
* [hbanzon](https://github.com/hbanzon)
* [ephremshiferaw](https://github.com/ephremshiferaw)
* [kmjonmastro](https://github.com/kmjonmastro)
* [streaming](https://github.com/streaming)
* [PureWeen](https://github.com/PureWeen)
* [bokmadsen](https://github.com/bokmadsen)
* [jfversluis](https://github.com/jfversluis)
* [Westat](https://github.com/Westat-Transportation)
* [jasonmereckixpo](https://github.com/jasonmereckixpo)This wouldn't be possible without all these great developer posts, articles and references:
#####iOS References:
* http://www.rapidvaluesolutions.com/tech_blog/geofencing-using-core-location-for-regional-monitoring-in-ios-applications/
* http://hayageek.com/ios-geofencing-api/
* http://developer.xamarin.com/recipes/ios/multitasking/geofencing/
* http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
* http://stackoverflow.com/questions/24543814/diddeterminestate-not-always-called#####Android References:
* http://paulusworld.com/technical/android-geofences-update
* http://sysmagazine.com/posts/210162/
* http://www.zionsoft.net/2014/11/google-play-services-locations-2/
* https://github.com/xamarin/monodroid-samples/blob/master/wear/Geofencing/Geofencing/GeofenceTransitionsIntentService.cs
* http://stackoverflow.com/questions/19505614/android-geofence-eventually-stop-getting-transition-intents/19521823#19521823
* https://github.com/googlesamples/android-play-location/blob/master/Geofencing/app/src/main/java/com/google/android/gms/location/sample/geofencing/MainActivity.java
* http://aboutyusata.blogspot.com/2013/08/getting-gps-reading-in-background-in.html?m=1
* http://developer.android.com/guide/components/bound-services.html
* https://software.intel.com/en-us/android/articles/implementing-map-and-geofence-features-in-android-business-apps
* https://github.com/CesarValiente/GeofencesDemo
* https://github.com/googlesamples/android-play-location
* http://www.toptal.com/android/android-developers-guide-to-google-location-services-api/#remote-developer-jo
* http://stackoverflow.com/questions/19434999/android-geofence-only-works-with-opened-app#####General References:
* http://whatis.techtarget.com/definition/geofencing
* http://welltechnically.com/?p=4691
* http://jwegan.com/growth-hacking/effective-geofencing/
* https://github.com/cowbell/cordova-plugin-geofenceThanks!
#### License
Licensed under main repo license