1

Я пытаюсь создать приложение с помощью API карт Google и Geofence API, чтобы сделать круговую область в моих марках на карте. Когда пользователь вводит эти круговые области, они будут получать уведомление для предупреждения при входе или выходе.Geofence не отображается в моем приложении карты

Я прочитал все учебники, которые нашел и не могу работать, я не знаю, в чем проблема.

КОД:

Я создал activity_maps.xml и класс MapsActivity контролировать функцию карты и реализации класса GeoFence вместе с MapsActivity, но геозон Dont появляются потому, что GoogleApiClient не может подключиться. Я не знаю почему.

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"; 
    } 
} 

Ошибка является Toast ти сообщение "Not Connected"

+0

Проблема, похоже, связана с GoogleApiClient. Для этого вы разместили много кода. Пожалуйста, следуйте руководству сообщества для размещения вопроса. Приведите минимальный, полный пример. – KayAnn

+0

Итак, где вы инициализируете Geofence API? Я не могу найти его в вашей базе кода. (извините, если я пропустил это) – KayAnn

ответ

0

Вызов LocationServices.GeofencingApi.addGeofences внутри метода onConnected в вашем 'MapsActivity.class'. Это гарантирует, что вы только попытаетесь добавить геообъекты, когда подключен GoogleAPIClient.