diff --git a/app/build.gradle b/app/build.gradle index 34bae3b..d97dbd5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,6 +43,7 @@ dependencies { 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' +// implementation "com.android.support:support-compat:28.0.0" // okhttp implementation 'com.squareup.okhttp3:okhttp:4.9.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fb7b89b..b2cdc54 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,11 @@ - + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/a1/nextlocation/fragments/HomeFragment.java b/app/src/main/java/com/a1/nextlocation/fragments/HomeFragment.java index 27970a4..db67ec8 100644 --- a/app/src/main/java/com/a1/nextlocation/fragments/HomeFragment.java +++ b/app/src/main/java/com/a1/nextlocation/fragments/HomeFragment.java @@ -2,6 +2,8 @@ package com.a1.nextlocation.fragments; import android.Manifest; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; @@ -19,6 +21,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; @@ -61,6 +64,8 @@ public class HomeFragment extends Fragment implements LocationListener { private int color; private Location currentLocation; private Overlay allLocationsOverlay; + private GeofenceInitalizer initializer; + private final static String CHANNEL_ID = "next_location01"; @Override public void onCreate(Bundle savedInstanceState) { @@ -143,6 +148,7 @@ public class HomeFragment extends Fragment implements LocationListener { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + initializer = new GeofenceInitalizer(requireContext(),requireActivity()); initMap(view); } @@ -249,6 +255,7 @@ public class HomeFragment extends Fragment implements LocationListener { private void addLocations() { // get the locations of the current route or all locations List locations = RouteHandler.INSTANCE.isFollowingRoute() ? RouteHandler.INSTANCE.getCurrentRoute().getLocations() : LocationListManager.INSTANCE.getLocationList(); + initializer.removeGeoFences(); final ArrayList items = new ArrayList<>(locations.size()); // marker icon Drawable marker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_location_on_24); @@ -312,7 +319,9 @@ public class HomeFragment extends Fragment implements LocationListener { * @param locations the locations to add geofences for */ private void addGeofences(List locations) { - GeofenceInitalizer initializer = new GeofenceInitalizer(requireContext()); + + Log.d(TAG, "addGeofences: adding geofences!"); + initializer.init(locations); } @@ -382,9 +391,31 @@ public class HomeFragment extends Fragment implements LocationListener { public void onLocationVisited(com.a1.nextlocation.data.Location location) { Data.INSTANCE.visitLocation(location); + showNotification(location); } + private void showNotification(com.a1.nextlocation.data.Location location) { + + NotificationManager mNotificationManager = (NotificationManager) requireActivity().getSystemService(Context.NOTIFICATION_SERVICE); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + int importance = NotificationManager.IMPORTANCE_LOW; + NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "next_location", importance); + notificationChannel.enableLights(true); + notificationChannel.enableVibration(true); + notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); + mNotificationManager.createNotificationChannel(notificationChannel); + } + + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(requireContext(),CHANNEL_ID) + .setSmallIcon(R.drawable.ic_launcher_foreground) + .setContentTitle(getString(R.string.notification_title)) + .setContentText(getString(R.string.notification_text,location.getName())) + .setAutoCancel(true); + + mNotificationManager.notify(0,mBuilder.build()); + } + // empty override methods for the LocationListener @Override diff --git a/app/src/main/java/com/a1/nextlocation/geofencing/GeoFenceBroadcastReceiver.java b/app/src/main/java/com/a1/nextlocation/geofencing/GeoFenceBroadcastReceiver.java index 37c49a4..382cad8 100644 --- a/app/src/main/java/com/a1/nextlocation/geofencing/GeoFenceBroadcastReceiver.java +++ b/app/src/main/java/com/a1/nextlocation/geofencing/GeoFenceBroadcastReceiver.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.util.Log; +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; @@ -20,6 +21,7 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); + Log.i(TAG, "onReceive: RECEIVED GEOFENCE STUFF"); if (geofencingEvent.hasError()) { String errorMessage = GeofenceStatusCodes @@ -40,7 +42,8 @@ public class GeoFenceBroadcastReceiver extends BroadcastReceiver { if (geofence.getRequestId().equals(l.getName())) { l.setVisited(true); // let the homefragment know that we are close to a location - + Data.INSTANCE.getLocationProximityListener().onLocationVisited(l); + Log.d(TAG, "onReceive: VISITED LOCATION " + l.getName()); break; } } diff --git a/app/src/main/java/com/a1/nextlocation/geofencing/GeoFencingHelper.java b/app/src/main/java/com/a1/nextlocation/geofencing/GeoFencingHelper.java index dd9e8d4..01f6335 100644 --- a/app/src/main/java/com/a1/nextlocation/geofencing/GeoFencingHelper.java +++ b/app/src/main/java/com/a1/nextlocation/geofencing/GeoFencingHelper.java @@ -44,7 +44,7 @@ public class GeoFencingHelper extends ContextWrapper { } Intent intent = new Intent(this, GeoFenceBroadcastReceiver.class); - pendingIntent = PendingIntent.getBroadcast(this, 2607, intent, PendingIntent.FLAG_UPDATE_CURRENT); + pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return pendingIntent; } diff --git a/app/src/main/java/com/a1/nextlocation/geofencing/GeofenceInitalizer.java b/app/src/main/java/com/a1/nextlocation/geofencing/GeofenceInitalizer.java index 874c6b8..7a1af31 100644 --- a/app/src/main/java/com/a1/nextlocation/geofencing/GeofenceInitalizer.java +++ b/app/src/main/java/com/a1/nextlocation/geofencing/GeofenceInitalizer.java @@ -1,12 +1,16 @@ package com.a1.nextlocation.geofencing; import android.Manifest; +import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Build; import android.util.Log; +import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import com.a1.nextlocation.data.Data; import com.a1.nextlocation.data.Location; @@ -15,27 +19,53 @@ 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 com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; import org.osmdroid.util.GeoPoint; import java.util.List; +import static android.content.ContentValues.TAG; + public class GeofenceInitalizer { + private final Activity activity; private GeofencingClient geofencingClient; private GeoFencingHelper geoFencingHelper; private final Context context; private final String TAG = GeofenceInitalizer.class.getCanonicalName(); private List locations; + private int BACKGROUND_LOCATION_ACCESS_REQUEST_CODE = 10002; - public GeofenceInitalizer(Context context) { + public GeofenceInitalizer(Context context, Activity activity) { this.context = context; + this.activity = activity; } public void init(List locations) { + if (!checkFineLocationPermission()) return; + geofencingClient = LocationServices.getGeofencingClient(context); geoFencingHelper = new GeoFencingHelper(context); this.locations = locations; - addFences(); + if (Build.VERSION.SDK_INT >= 29) { + //If API is higher then 29 we need background permission + + if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { + addFences(); + } else { + //Permission is not granted!! Need to request it.. + if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { + //We show a dialog and ask for permission + ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); + } else { + ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); + + } + } + } else { + addFences(); + } } private void addFences() { @@ -45,18 +75,35 @@ public class GeofenceInitalizer { } } + public void removeGeoFences() { + geofencingClient = LocationServices.getGeofencingClient(context); + geoFencingHelper = new GeoFencingHelper(context); + + PendingIntent pendingIntent = geoFencingHelper.getPendingIntent(); + + geofencingClient.removeGeofences(pendingIntent) + .addOnSuccessListener(aVoid -> Log.d(TAG, "Geofence is removed... ")) + .addOnFailureListener(e -> Log.d(TAG, e.getLocalizedMessage())); + if (this.locations != null) this.locations.clear(); + + } + private void addGeofence(GeoPoint p, String name) { - Geofence geofence = geoFencingHelper.getGeofence(name, p, 30); + if (!checkFineLocationPermission()) return; + + Geofence geofence = geoFencingHelper.getGeofence(name, p, 45); 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"); + Log.i(TAG, "addGeofence: added geofence"); }).addOnFailureListener(v -> { - + Log.e(TAG, "addGeofence: failure adding geofence " + v.getMessage()); }); + Log.i(TAG, "addGeofence: added geofence to client"); + } + + private boolean checkFineLocationPermission() { + return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; } } diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b18831e..367dd5e 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -26,4 +26,6 @@ Chinees HELP Onderaan het scherm zijn verschillende knoppen te zien. Deze knoppen hebben de volgende functies: \n\nLocaties: toont een lijst met alle locaties die bezocht kunnen worden. Elke locatie wordt kort beschreven. \n\nRoutes: Toont een lijst met alle routes die gelopen kunnen worden. Van elke route wordt een omschrijving gegeven. \n\nStatistieken: Toont persoonlijke statistieken. \n\nInstellingen: Hier kunnen app-instellingen worden aangepast naar eigen voorkeur. \n\nEen locatie ingedrukt houden laat extra informatie zien over de gekozen locatie + Je bent dicht bij een locatie! + Je bent bijna bij %1$s \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c965083..0c084f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,4 +25,6 @@ Chinese HELP Hasn\'t been translated yet + You\'re close to a location! + You\'re almost at %1$s \ No newline at end of file