Develop #5
@@ -40,6 +40,7 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<receiver android:name=".geofencing.GeoFenceBroadcastReceiver"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -11,6 +11,15 @@ public enum Data {
|
||||
private int locationsVisited = 0;
|
||||
private long totalTime = 0;
|
||||
private double zoom = 0;
|
||||
private LocationProximityListener locationProximityListener;
|
||||
|
||||
public LocationProximityListener getLocationProximityListener() {
|
||||
return locationProximityListener;
|
||||
}
|
||||
|
||||
public void setLocationProximityListener(LocationProximityListener locationProximityListener) {
|
||||
this.locationProximityListener = locationProximityListener;
|
||||
}
|
||||
|
||||
public double getZoom() {
|
||||
return zoom;
|
||||
@@ -50,5 +59,10 @@ public enum Data {
|
||||
return locationsVisited;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LocationProximityListener {
|
||||
void onLocationVisited(Location location);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public class Location implements Parcelable {
|
||||
private String imageUrl;
|
||||
private String iconUrl;
|
||||
|
||||
private boolean visited;
|
||||
|
||||
public Location(@NotNull String name, String coordinates, String description, @Nullable String imageUrl) {
|
||||
this.name = name;
|
||||
this.coordinates = coordinates;
|
||||
@@ -171,4 +173,12 @@ public class Location implements Parcelable {
|
||||
parcel.writeString(description);
|
||||
parcel.writeString(imageUrl);
|
||||
}
|
||||
|
||||
public boolean isVisited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
public void setVisited(boolean visited) {
|
||||
this.visited = visited;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import com.a1.nextlocation.R;
|
||||
import com.a1.nextlocation.data.Data;
|
||||
import com.a1.nextlocation.data.RouteHandler;
|
||||
import com.a1.nextlocation.geofencing.GeofenceInitalizer;
|
||||
import com.a1.nextlocation.json.DirectionsResult;
|
||||
import com.a1.nextlocation.network.ApiHandler;
|
||||
import com.a1.nextlocation.recyclerview.LocationListManager;
|
||||
@@ -71,6 +72,7 @@ public class HomeFragment extends Fragment implements LocationListener {
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
|
||||
color = requireContext().getColor(R.color.red);
|
||||
Data.INSTANCE.setLocationProximityListener(this::onLocationVisited);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,6 +219,8 @@ public class HomeFragment extends Fragment implements LocationListener {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* displays the route that is currently being followed as a red line
|
||||
*/
|
||||
@@ -299,6 +303,17 @@ public class HomeFragment extends Fragment implements LocationListener {
|
||||
mapView.getOverlays().add(allLocationsOverlay);
|
||||
Log.d(TAG, "addLocations: successfully added locations");
|
||||
|
||||
addGeofences(locations);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the geofences for the currently active locations
|
||||
* @param locations the locations to add geofences for
|
||||
*/
|
||||
private void addGeofences(List<com.a1.nextlocation.data.Location> locations) {
|
||||
GeofenceInitalizer initializer = new GeofenceInitalizer(requireContext());
|
||||
initializer.init(locations);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,6 +380,11 @@ public class HomeFragment extends Fragment implements LocationListener {
|
||||
|
||||
}
|
||||
|
||||
public void onLocationVisited(com.a1.nextlocation.data.Location location) {
|
||||
Data.INSTANCE.visitLocation(location);
|
||||
|
||||
}
|
||||
|
||||
// empty override methods for the LocationListener
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.a1.nextlocation.geofencing;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.a1.nextlocation.data.Location;
|
||||
import com.a1.nextlocation.recyclerview.LocationListManager;
|
||||
import com.google.android.gms.location.Geofence;
|
||||
import com.google.android.gms.location.GeofenceStatusCodes;
|
||||
import com.google.android.gms.location.GeofencingEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GeoFenceBroadcastReceiver extends BroadcastReceiver {
|
||||
private final String TAG = GeoFenceBroadcastReceiver.class.getCanonicalName();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
|
||||
|
||||
if (geofencingEvent.hasError()) {
|
||||
String errorMessage = GeofenceStatusCodes
|
||||
.getStatusCodeString(geofencingEvent.getErrorCode());
|
||||
Log.e(TAG, errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the transition type.
|
||||
int geofenceTransition = geofencingEvent.getGeofenceTransition();
|
||||
|
||||
switch (geofenceTransition) {
|
||||
case Geofence.GEOFENCE_TRANSITION_ENTER:
|
||||
List<Geofence> geofenceList = geofencingEvent.getTriggeringGeofences();
|
||||
// loop through list of geofences
|
||||
for (Geofence geofence : geofenceList) {
|
||||
for (Location l : LocationListManager.INSTANCE.getLocationList()) {
|
||||
if (geofence.getRequestId().equals(l.getName())) {
|
||||
l.setVisited(true);
|
||||
// let the homefragment know that we are close to a location
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Geofence.GEOFENCE_TRANSITION_EXIT:
|
||||
Log.d(TAG, "onReceive: exiting geofence...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.a1.nextlocation.geofencing;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.provider.SyncStateContract;
|
||||
|
||||
import com.google.android.gms.location.Geofence;
|
||||
import com.google.android.gms.location.GeofencingRequest;
|
||||
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
|
||||
public class GeoFencingHelper extends ContextWrapper {
|
||||
private PendingIntent pendingIntent;
|
||||
|
||||
public GeoFencingHelper(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
public GeofencingRequest getGeoFencingRequest(Geofence geofence) {
|
||||
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
|
||||
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
|
||||
builder.addGeofence(geofence);
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
public Geofence getGeofence(String ID, GeoPoint point, float radius) {
|
||||
|
||||
return new Geofence.Builder()
|
||||
.setCircularRegion(point.getLatitude(), point.getLongitude(), radius)
|
||||
.setRequestId(ID)
|
||||
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
|
||||
Geofence.GEOFENCE_TRANSITION_EXIT)
|
||||
.setLoiteringDelay(5000)
|
||||
.setExpirationDuration(Geofence.NEVER_EXPIRE)
|
||||
.build();
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
if (pendingIntent != null) {
|
||||
return pendingIntent;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this, GeoFenceBroadcastReceiver.class);
|
||||
pendingIntent = PendingIntent.getBroadcast(this, 2607, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
return pendingIntent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.a1.nextlocation.geofencing;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
|
||||
import com.a1.nextlocation.data.Data;
|
||||
import com.a1.nextlocation.data.Location;
|
||||
import com.a1.nextlocation.recyclerview.LocationListManager;
|
||||
import com.google.android.gms.location.Geofence;
|
||||
import com.google.android.gms.location.GeofencingClient;
|
||||
import com.google.android.gms.location.GeofencingRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GeofenceInitalizer {
|
||||
private GeofencingClient geofencingClient;
|
||||
private GeoFencingHelper geoFencingHelper;
|
||||
private final Context context;
|
||||
private final String TAG = GeofenceInitalizer.class.getCanonicalName();
|
||||
private List<Location> locations;
|
||||
|
||||
public GeofenceInitalizer(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void init(List<Location> locations) {
|
||||
geofencingClient = LocationServices.getGeofencingClient(context);
|
||||
geoFencingHelper = new GeoFencingHelper(context);
|
||||
this.locations = locations;
|
||||
addFences();
|
||||
}
|
||||
|
||||
private void addFences() {
|
||||
for (Location location : locations) {
|
||||
GeoPoint t = new GeoPoint(location.getLat(), location.getLong());
|
||||
addGeofence(t, location.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void addGeofence(GeoPoint p, String name) {
|
||||
Geofence geofence = geoFencingHelper.getGeofence(name, p, 30);
|
||||
GeofencingRequest geofencingRequest = geoFencingHelper.getGeoFencingRequest(geofence);
|
||||
PendingIntent pendingIntent = geoFencingHelper.getPendingIntent();
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
geofencingClient.addGeofences(geofencingRequest, pendingIntent).addOnSuccessListener(v -> {
|
||||
Log.d(TAG, "addGeofence: added geofence");
|
||||
}).addOnFailureListener(v -> {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user