android - added - Manejo de transiciones de múltiples geofences con área común.
geofences added android (3)
Si tengo estas dos geofences, luego de registrar estas geofences debería recibir una notificación cuando esté ingresando o saliendo de la circunferencia de estos círculos. Sin embargo, no quiero que mi aplicación envíe una notificación si me estoy moviendo a través del área común, es decir, de un círculo a otro.
¿Es posible? Si es así, entonces ¿cómo?
Esta puede ser una alternativa:
Todas las geofences tienen una identificación; No estoy seguro de que deban ser únicos, pero para esta discusión digamos que deben ser únicos. En sus dos ejemplos de geofence, usemos las identificaciones "fenceHome-1" y "fenceHome-2" para las que se muestran y una tercera llamada "someOther-1" que no se muestra.
Ahora, lo que puede hacer es crear una variable para almacenar la geofence actual en la que se encuentra el usuario. En este ejemplo, será una cadena con el id de geofence. Llamémoslo
String currentGeofence = new String();
Cuando el usuario ingresa un nuevo geofence, ahora puede verificar si los geofenceIds son los mismos.
/**
geofenceEntered get from the Intent. Should be "fenceHome-1" or "fenceHome-2" or "someOther=1"
*/
public void enteredGeoFence(String geofenceEntered) {
// strip off the "-1" or "-2"
geofenceEntered = geofenceEntered.stripOff();
if (currentGoofence.equals(geofenceEntered) == false} {
// user entered a new geofence Ex: "SomeOther-1" to "fenceHome-1"
sendNotification(geofenceEntered, .....);
currentGeofence = geofencecEntered;
} else {
// user entered a geofence with in the same ''area''. Ex: "fenceHome-1" to "fenceHome-2"
// do nothing
}
}
Así es como lo haría. Jugar con todas esas matemáticas es demasiado difícil. Solo establece una convención de nomenclatura inteligente para tus ID de geofence. La clave es el nombramiento de las geofences .
En el mundo real, currentGeofence tendría que ser una colección, ya que un usuario puede estar en múltiples geofences y geofenceExit () tendría que eliminarse de currentGeofence.
Otra cosa que debe recordar del administrador de notificaciones de Android es: si envía la misma notificación dos veces, solo enviará una notificación. Esto podría ser utilizado para su ventaja.
Tendrá que usar una class para controlar su cercado:
public class GeofenceReceiver extends BroadcastReceiver {
Context context;
Intent broadcastIntent = new Intent();
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);
if (LocationClient.hasError(intent)) {
handleError(intent);
} else {
handleEnterExit(intent);
}
}
private void handleError(Intent intent){
// Get the error code
int errorCode = LocationClient.getErrorCode(intent);
// Get the error message
String errorMessage = LocationServiceErrorMessages.getErrorString(
context, errorCode);
// Log the error
Log.e(GeofenceUtils.APPTAG,
context.getString(R.string.geofence_transition_error_detail,
errorMessage));
// Set the action and error message for the broadcast intent
broadcastIntent
.setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR)
.putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage);
// Broadcast the error *locally* to other components in this app
LocalBroadcastManager.getInstance(context).sendBroadcast(
broadcastIntent);
}
private void handleEnterExit(Intent intent) {
// Get the type of transition (entry or exit)
int transition = LocationClient.getGeofenceTransition(intent);
// Test that a valid transition was reported
if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER)
|| (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) {
// Post a notification
List<Geofence> geofences = LocationClient
.getTriggeringGeofences(intent);
String[] geofenceIds = new String[geofences.size()];
String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER,
geofenceIds);
String transitionType = GeofenceUtils
.getTransitionString(transition);
for (int index = 0; index < geofences.size(); index++) {
Geofence geofence = geofences.get(index);
...do something with the geofence entry or exit. I''m saving them to a local sqlite db
}
// Create an Intent to broadcast to the app
broadcastIntent
.setAction(GeofenceUtils.ACTION_GEOFENCE_TRANSITION)
.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES)
.putExtra(GeofenceUtils.EXTRA_GEOFENCE_ID, geofenceIds)
.putExtra(GeofenceUtils.EXTRA_GEOFENCE_TRANSITION_TYPE,
transitionType);
LocalBroadcastManager.getInstance(MyApplication.getContext())
.sendBroadcast(broadcastIntent);
// Log the transition type and a message
Log.d(GeofenceUtils.APPTAG, transitionType + ": " + ids);
Log.d(GeofenceUtils.APPTAG,
context.getString(R.string.geofence_transition_notification_text));
// In debug mode, log the result
Log.d(GeofenceUtils.APPTAG, "transition");
// An invalid transition was reported
} else {
// Always log as an error
Log.e(GeofenceUtils.APPTAG,
context.getString(R.string.geofence_transition_invalid_type,
transition));
}
}
//Posts a notification in the notification bar when a transition
private void sendNotification(String transitionType, String locationName) {
// Create an explicit content Intent that starts the main Activity
Intent notificationIntent = new Intent(context, MainActivity.class);
// Construct a task stack
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the main Activity to the task stack as the parent
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack
PendingIntent notificationPendingIntent = stackBuilder
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that''s compatible with platform versions
// >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
// Set the notification contents
builder.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(transitionType + ": " + locationName)
.setContentText(
context.getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Get an instance of the Notification manager
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
Debe crear escuchas para cada una de las áreas que desea monitorear, digamos listener1 y listener2. Para optimizar ambas áreas e integrarla, el mejor enfoque es hacer una cuadrícula utilizando MongoDB, que en tal caso incluso le permite integrar más de dos puntos, mientras construye una cuadrícula.
Suponiendo que vas a obtener un polígono en forma de algunos puntos Lat-Lon, entonces puedes generar una grid como la siguiente:
# Method to get the min and max values for the polygon
def get_bounding_box(coords)
# get max and min coords
max = coords.inject({lat:0, lon:0}) do |max, c|
max[:lon] = c[0] if c[0] > max[:lon]
max[:lat] = c[1] if c[1] > max[:lat]
max
end
min = coords.inject({lat:MAX_LAT, lon:MAX_LON}) do |min, c|
min[:lon] = c[0] if c[0] < min[:lon]
min[:lat] = c[1] if c[1] < min[:lat]
min
end
# add a little padding to the max and min
max.each {|k, v| max[k] += 1 }
min.each {|k, v| min[k] -= 1 }
{min: min, max: max}
end
def generate_grid(bounds)
lon_range = bounds[:min][:lon]...bounds[:max][:lon]
lat_range = bounds[:min][:lat]...bounds[:max][:lat]
grid = []
lon_range.each do |lon|
lat_range.each do |lat|
grid << [lon + 0.25, lat + 0.25]
grid << [lon + 0.25, lat + 0.75]
grid << [lon + 0.75, lat + 0.25]
grid << [lon + 0.75, lat + 0.75]
end
end
grid
end
Este enfoque le permite lograr un geofencing muy eficiente con redes inteligentes para monitorear áreas objetivo:
Más recientemente, MongoDB también agregó soporte para Android , lo que proporciona una manera fácil para la integración de back-end de su aplicación Android. De hecho, se espera que el desarrollo de geofencing con datos distribuidos inteligentes tenga un número creciente de applications .
muy esquemáticamente:
boolean isTransition1, isTransition2, isTransition, insideCircle1, insideCircle2, insideUnion, insideUnionPrev;
if (isTransition1 | isTransition2) {
insideCircle1 = (dist(currPosition, centerCircle1) < radius1);
insideCircle2 = (dist(currPosition, centerCircle2) < radius2);
insideUnionPrev = insideUnion;
insideUnion = insideCircle1 | insideCircle;
isTransition = (insideUnion != insideUnionPrev);
if (isTransition & insideUnion) println("Moved into region");
if (isTransition & !insideUnion) println("Moved out of region");
}