J'ai une application qui a commencé avec l'exemple de code de géofencing de Google. Cela fonctionne très bien pendant quelques jours et j'obtiens toutes les intentions de transition comme je m'y attendais. Cependant, après un peu de temps, quelque chose comme 3 jours, l'application cesse d'obtenir ces intentions, et je ne sais pas pourquoi.
Lorsque je crée mes clôtures, je règle la durée d'expiration sur Geofence.NEVER_EXPIRE
Voici mon IntentService où j'obtiens les intentions de transition avant qu'elles ne cessent de fonctionner:
public class ReceiveTransitionsIntentService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
Intent broadcastIntent = new Intent();
broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES);
// First check for errors
if (LocationClient.hasError(intent)) {
...handle errors
} else {
// 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
NEVER GETS HERE
} else {
...log error
}
}
}
}
Voici une partie pertinente du manifeste:
<service
Android:name="com.aol.Android.geofence.ReceiveTransitionsIntentService"
Android:exported="false" >
</service>
Dans ma classe GeofenceRequester, il est presque identique à l'exemple de code. Voici les parties pertinentes:
// Get a PendingIntent that Location Services issues when a geofence transition occurs
mGeofencePendingIntent = createRequestPendingIntent();
// Send a request to add the current geofences
mLocationClient.addGeofences(mCurrentGeofences, mGeofencePendingIntent, this);
private PendingIntent createRequestPendingIntent() {
// Create an Intent pointing to the IntentService
Intent intent = new Intent(context, ReceiveTransitionsIntentService.class);
return PendingIntent.getService(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}
Quelqu'un peut-il voir pourquoi cela cesserait de fonctionner?
Ainsi, après avoir joué un peu avec cela, il semble que le ReceiveTransitionsIntentService tel que défini dans l'exemple de code arrête de recevoir les notifications lorsque l'application n'est pas là. Je pense que c'est un gros problème avec l'exemple de code ... On dirait que ça fera trébucher des gens comme moi.
J'ai donc utilisé un récepteur de diffusion à la place, et jusqu'à présent, il semble fonctionner à partir de mes tests.
Ajoutez ceci au manifeste:
<receiver Android:name="com.aol.Android.geofence.GeofenceReceiver"
Android:exported="false">
<intent-filter >
<action Android:name="com.aol.Android.geofence.ACTION_RECEIVE_GEOFENCE"/>
</intent-filter>
</receiver>
Ensuite, dans la classe GeofenceRequester, vous devez modifier la méthode createRequestPendingIntent afin qu'elle passe à votre BroadcastReceiver au lieu de ReceiveTransitionsIntentService
private PendingIntent createRequestPendingIntent() {
// If the PendingIntent already exists
if (null != mGeofencePendingIntent) {
// Return the existing intent
return mGeofencePendingIntent;
// If no PendingIntent exists
} else {
// Create an Intent pointing to the IntentService
Intent intent = new Intent("com.aol.Android.geofence.ACTION_RECEIVE_GEOFENCE");
// Intent intent = new Intent(context, ReceiveTransitionsIntentService.class);
/*
* Return a PendingIntent to start the IntentService.
* Always create a PendingIntent sent to Location Services
* with FLAG_UPDATE_CURRENT, so that sending the PendingIntent
* again updates the original. Otherwise, Location Services
* can't match the PendingIntent to requests made with it.
*/
return PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
}
Ensuite, j'ai ajouté la classe GeofenceReceiver qui ressemble à ceci:
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 is
* detected. If the user clicks the notification, control goes to the main
* Activity.
*
* @param transitionType
* The type of transition that occurred.
*
*/
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());
}
}
J'espère que cela aide quelqu'un d'autre.
Voici les raisons pour lesquelles l'application n'obtient pas d'intentions en attente selon la documentation officielle de Google -
1.L'appareil est redémarré.
2. L'application est désinstallée et réinstallée.
3.Les données de l'application sont effacées.
4. Les données des services Google Play sont effacées.
5.L'application a reçu une alerte GEOFENCE_NOT_AVAILABLE. (Lorsque Android Fournisseur de localisation est désactivé)
Vous devez réenregistrer la clôture géographique après ces événements.
Dans mon cas, le fournisseur de localisation est désactivé et le périphérique est également redémarré, c'est pourquoi je n'obtenais pas les intentions en attente.