1

J'essaie de créer une application à l'aide de l'API google maps et de l'API Geofence pour créer une zone circulaire dans mes marques sur la carte. Lorsque l'utilisateur entre dans ces zones circulaires, il recevra une notification d'alerte lorsqu'il entrera ou sortira.Geofence ne s'affiche pas dans mon application de carte

J'ai lu tous les tutoriels que j'ai trouvé et je ne peux pas travailler, je ne sais pas quel est le problème.

CODE:

J'ai créé un activity_maps.xml et une classe de MapsActivity pour contrôler la fonction de la carte et la mise en œuvre de la classe geofence avec MapsActivity, mais les geofences DonT apparaissent parce que le GoogleApiClient ne peut pas se connecter. Je ne sais pas pourquoi.

activity_maps.xml

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" 
android:layout_height="match_parent" android:id="@+id/map" tools:context=".MapsActivity" 
android:name="com.google.android.gms.maps.SupportMapFragment" /> 

MapsActivity.class

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> { 

protected static final String TAG = "MapsActivity"; 
protected GoogleApiClient mGoogleApiClient; 
private PendingIntent mGeofencePendingIntent; 
private GoogleMap mMap; 
protected ArrayList<Geofence> mGeofenceList; 
private boolean mGeofencesAdded; 
private boolean firstTime = true; 
private SharedPreferences mSharedPreferences; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maps); 
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 
    mGeofenceList = new ArrayList<Geofence>(); 
    mGeofencePendingIntent = null; 
    mSharedPreferences = getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, MODE_PRIVATE); 
    mGeofencesAdded = mSharedPreferences.getBoolean(Constants.GEOFENCES_ADDED_KEY, false); 
    populateGeofenceList(); 
    buildGoogleApiClient(); 

} 

@Override 
public void onMapReady(GoogleMap googleMap) { 
    mMap = googleMap; 
    mMap.setMyLocationEnabled(true); 
    if (mMap != null) { 

     mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() { 
      @Override 
      public void onMyLocationChange(Location arg0) { 
       // TODO Auto-generated method stub 
       if (firstTime) { 
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(arg0.getLatitude(), arg0.getLongitude()), 18); 
        mMap.animateCamera(cameraUpdate); 
        firstTime = false; 
       } 

      } 
     }); 
    } 
    LatLng NewPointer = new LatLng(-22.9274767,-47.0775973); 
    //Drawable iconDrawable = getResources().getDrawable(R.drawable.markernp); 
    //Bitmap iconBmp = ((BitmapDrawable) iconDrawable).getBitmap(); 
    //.icon(BitmapDescriptorFactory.fromBitmap(iconBmp))); 
    mMap.addMarker(new MarkerOptions().position(NewPointer).title("Title").snippet("Subtitle")); 
    addGeofencesButtonHandler(); 
} 

protected synchronized void buildGoogleApiClient() { 
    mGoogleApiClient = new GoogleApiClient.Builder(this) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .addApi(LocationServices.API) 
      .build(); 
} 

@Override 
protected void onStart() { 
    super.onStart(); 
    mGoogleApiClient.connect(); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    mGoogleApiClient.disconnect(); 
} 

public void populateGeofenceList() { 
    LatLng NewPointer = new LatLng(-22.9274767,-47.0775973); 
     mGeofenceList.add(new Geofence.Builder() 
       .setRequestId("npGeofence") 
       .setCircularRegion(NewPointer.latitude, NewPointer.longitude, 200) 
       .setExpirationDuration(Geofence.NEVER_EXPIRE) 
       .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) 
       .build()); 
} 

private GeofencingRequest getGeofencingRequest() { 
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); 
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); 
    builder.addGeofences(mGeofenceList); 
    return builder.build(); 
} 

public void addGeofencesButtonHandler() { 
    if (!mGoogleApiClient.isConnected()) { 
     Toast.makeText(this, "not connected", Toast.LENGTH_SHORT).show(); 
     return; 
    } 

    try { 
     LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       getGeofencingRequest(), 
       getGeofencePendingIntent() 
     ).setResultCallback(this); 
    } catch (SecurityException securityException) { 
     logSecurityException(securityException); 
    } 
} 

private void logSecurityException(SecurityException securityException) { 
    Log.e(TAG, "Invalid location permission. " + 
      "You need to use ACCESS_FINE_LOCATION with geofences", securityException); 
} 

@Override 
public void onConnected(Bundle bundle) { 

} 

@Override 
public void onConnectionSuspended(int i) { 

} 

@Override 
public void onConnectionFailed(ConnectionResult connectionResult) { 

} 


@Override 
public void onResult(Status status) { 
    if (status.isSuccess()) { 
     mGeofencesAdded = !mGeofencesAdded; 
     SharedPreferences.Editor editor = mSharedPreferences.edit(); 
     editor.putBoolean(Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded); 
     editor.apply(); 
    } else { 
     String errorMessage = GeofenceErrorMessages.getErrorString(this, 
       status.getStatusCode()); 
     Log.e(TAG, errorMessage); 
    } 
} 

private PendingIntent getGeofencePendingIntent() { 
    if (mGeofencePendingIntent != null) { 
     return mGeofencePendingIntent; 
    } 
    Intent intent = new Intent(this, GeofenceTransitionsIntentService.class); 
    return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
} 

Contants.class

public final class Constants { 

private Constants() { 
} 

public static final String PACKAGE_NAME = "com.google.android.gms.location.Geofence"; 

public static final String SHARED_PREFERENCES_NAME = PACKAGE_NAME + ".SHARED_PREFERENCES_NAME"; 

public static final String GEOFENCES_ADDED_KEY = PACKAGE_NAME + ".GEOFENCES_ADDED_KEY"; 

/** 
* Used to set an expiration time for a geofence. After this amount of time Location Services 
* stops tracking the geofence. 
*/ 
public static final long GEOFENCE_EXPIRATION_IN_HOURS = 12; 

/** 
* For this sample, geofences expire after twelve hours. 
*/ 
public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = 
     GEOFENCE_EXPIRATION_IN_HOURS * 60 * 60 * 1000; 
public static final float GEOFENCE_RADIUS_IN_METERS = 1609; // 1 mile, 1.6 km 

/** 
* Map for storing information about airports in the San Francisco bay area. 
*/ 
public static final HashMap<String, LatLng> BAY_AREA_LANDMARKS = new HashMap<String, LatLng>(); 
static { 
    // San Francisco International Airport. 
    BAY_AREA_LANDMARKS.put("SFO", new LatLng(37.621313, -122.378955)); 

    // Googleplex. 
    BAY_AREA_LANDMARKS.put("GOOGLE", new LatLng(37.422611,-122.0840577)); 
} 

GeofenceErrorMessage.class

public class GeofenceErrorMessages { 
/** 
* Prevents instantiation. 
*/ 
private GeofenceErrorMessages() {} 

/** 
* Returns the error string for a geofencing error code. 
*/ 
public static String getErrorString(Context context, int errorCode) { 
    Resources mResources = context.getResources(); 
    switch (errorCode) { 
     case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: 
      return "geofence not avaliable"; 
     case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: 
      return "geofence to many geofences"; 
     case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: 
      return "geofence to many pending geofences"; 
     default: 
      return "unknown geofence error"; 
    } 
} 

GeofenceTransitionIntentService.class

public class GeofenceTransitionsIntentService extends IntentService { 

protected static final String TAG = "GeofenceTransitionsIS"; 

/** 
* This constructor is required, and calls the super IntentService(String) 
* constructor with the name for a worker thread. 
*/ 
public GeofenceTransitionsIntentService() { 
    // Use the TAG to name the worker thread. 
    super(TAG); 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
} 

/** 
* Handles incoming intents. 
* @param intent sent by Location Services. This Intent is provided to Location 
*    Services (inside a PendingIntent) when addGeofences() is called. 
*/ 
@Override 
protected void onHandleIntent(Intent intent) { 
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); 
    if (geofencingEvent.hasError()) { 
     String errorMessage = GeofenceErrorMessages.getErrorString(this, 
       geofencingEvent.getErrorCode()); 
     Log.e(TAG, errorMessage); 
     return; 
    } 

    // Get the transition type. 
    int geofenceTransition = geofencingEvent.getGeofenceTransition(); 

    // Test that the reported transition was of interest. 
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || 
      geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { 

     // Get the geofences that were triggered. A single event can trigger multiple geofences. 
     List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences(); 

     // Get the transition details as a String. 
     String geofenceTransitionDetails = getGeofenceTransitionDetails(
       this, 
       geofenceTransition, 
       triggeringGeofences 
     ); 

     // Send notification and log the transition details. 
     sendNotification(geofenceTransitionDetails); 
     Log.i(TAG, geofenceTransitionDetails); 
    } else { 
     // Log the error. 
     Log.e(TAG, "genfence transition invalid"); 
    } 
} 

/** 
* Gets transition details and returns them as a formatted string. 
* 
* @param context    The app context. 
* @param geofenceTransition The ID of the geofence transition. 
* @param triggeringGeofences The geofence(s) triggered. 
* @return      The transition details formatted as String. 
*/ 
private String getGeofenceTransitionDetails(
     Context context, 
     int geofenceTransition, 
     List<Geofence> triggeringGeofences) { 

    String geofenceTransitionString = getTransitionString(geofenceTransition); 

    // Get the Ids of each geofence that was triggered. 
    ArrayList triggeringGeofencesIdsList = new ArrayList(); 
    for (Geofence geofence : triggeringGeofences) { 
     triggeringGeofencesIdsList.add(geofence.getRequestId()); 
    } 
    String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList); 

    return geofenceTransitionString + ": " + triggeringGeofencesIdsString; 
} 

/** 
* Posts a notification in the notification bar when a transition is detected. 
* If the user clicks the notification, control goes to the MainActivity. 
*/ 
private void sendNotification(String notificationDetails) { 
    // Create an explicit content Intent that starts the main Activity. 
    Intent notificationIntent = new Intent(getApplicationContext(), MapsActivity.class); 

    // Construct a task stack. 
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 

    // Add the main Activity to the task stack as the parent. 
    stackBuilder.addParentStack(MapsActivity.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(this); 

    // Define the notification settings. 
    builder.setSmallIcon(R.mipmap.ic_launcher) 
      // In a real app, you may want to use a library like Volley 
      // to decode the Bitmap. 
      .setLargeIcon(BitmapFactory.decodeResource(getResources(), 
        R.mipmap.ic_launcher)) 
      .setColor(Color.RED) 
      .setContentTitle(notificationDetails) 
      .setContentText("geofence transition notification") 
        .setContentIntent(notificationPendingIntent); 

    // Dismiss notification once the user touches it. 
    builder.setAutoCancel(true); 

    // Get an instance of the Notification manager 
    NotificationManager mNotificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 

    // Issue the notification 
    mNotificationManager.notify(0, builder.build()); 
} 

/** 
* Maps geofence transition types to their human-readable equivalents. 
* 
* @param transitionType A transition type constant defined in Geofence 
* @return     A String indicating the type of transition 
*/ 
private String getTransitionString(int transitionType) { 
    switch (transitionType) { 
     case Geofence.GEOFENCE_TRANSITION_ENTER: 
      return "geofence transition ended"; 
     case Geofence.GEOFENCE_TRANSITION_EXIT: 
      return "genfence transition exited"; 
     default: 
      return "unknows geofence transition"; 
    } 
} 

L'erreur est un Toast cinque le message "Non connecté"

+0

Le problème semble être avec GoogleApiClient. Vous avez posté beaucoup de code pour cela. Veuillez suivre les directives de la communauté pour poster une question. Fournissez un exemple minimal et complet. – KayAnn

+0

Alors, où initialisez-vous l'API Geofence? Je ne peux pas le trouver dans votre base de code. (désolé si je l'ai manqué) – KayAnn

Répondre

0

Appel LocationServices.GeofencingApi.addGeofences dans la méthode onConnected dans votre 'MapsActivity.class'. Cela garantira que vous ne tentez d'ajouter des géofences que lorsque GoogleAPIClient est connecté.