I need to make android app with map and some markers. When i'm come within 10 meters to the marker, it becomes clickable, and on click plays audiotrack, then changes marker icon and shows another marker. I tried to use geofences, but i can't change icon or call MediaPlayer from BroadcastReciever or from other activity or service.
marker - center of geofence.
How can I change marker's icon and start audiotrack, when geofence triggers?
adding geofences in MapsActivity
private void createGeofences(){
if (Build.VERSION.SDK_INT >= 29) {
//We need background permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
for (int i=0; i < ARRAY_SIZE; i++){
addGeofence(latLngArray[i], GEOFENCE_RADIUS, Integer.toString(i));
}
}
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
//We show a dialog and ask for permission
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE);
}
}
}
private void addGeofence(LatLng latLng, float radius, String id){
Geofence geofence = GeofenceHelper.getGeofence(id, latLng, radius, Geofence.GEOFENCE_TRANSITION_ENTER);
GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence);
PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
geofencingClient.addGeofences(geofencingRequest, pendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Geofence Added...");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
String errorMessage = GeofenceHelper.getErrorString(e);
Log.d(TAG, "onFailure: " + errorMessage);
}
});
}
}
GeofenceHelper.class
public class GeofenceHelper extends ContextWrapper {
private static final int loiteringDelay = 0;
private static final String TAG = "GeofenceHelper";
PendingIntent pendingIntent;
public GeofenceHelper(Context base) {
super(base);
}
public GeofencingRequest getGeofencingRequest(Geofence geofence){
return new GeofencingRequest.Builder()
.addGeofence(geofence)
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.build();
}
public static Geofence getGeofence(String ID, LatLng latLng, float radius, int transitionTypes){
return new Geofence.Builder()
.setCircularRegion(latLng.latitude, latLng.longitude, radius)
.setRequestId(ID)
.setTransitionTypes(transitionTypes)
.setLoiteringDelay(loiteringDelay)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
}
public PendingIntent getPendingIntent(){
if(pendingIntent != null){
return pendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 956, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
public static String getErrorString(Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
switch (apiException.getStatusCode()) {
case GeofenceStatusCodes
.GEOFENCE_NOT_AVAILABLE:
return "GEOFENCE_NOT_AVAILABLE";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_GEOFENCES:
return "GEOFENCE_TOO_MANY_GEOFENCES";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "GEOFENCE_TOO_MANY_PENDING_INTENTS";
}
}
return e.getLocalizedMessage();
}
}
GeofenceBroadcastReciever.class
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GeofenceBroadcastReceiv";
//MediaPlayer mediaPlayer;
@Override
public void onReceive(Context context, Intent intent) {
// an Intent broadcast.
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
Log.d(TAG, "onReceive: Error receiving geofence event...");
return;
};
List<Geofence> geofenceList = geofencingEvent.getTriggeringGeofences();
String id = geofenceList.get(0).getRequestId();
switch (id){
case "0":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
case "1":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
case "2":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
case "3":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
case "4":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
case "5":
Toast.makeText(context, "Geofence " + id + " triggered.", Toast.LENGTH_SHORT).show();
}
}
}
MediaPlayer need context Well you can pass a context to the broadcast receiver. I assume (because you have not shown it) that you register your broadcast receiver in an Activity or App which are contexts. Multiple solutions:
MapsActivity.this
).Consumer<Integer> onCheckpointReached
) in the constructor of the broadcast receiver.As per accessing the specific track dynamically, you should not use such a switch but get a resource dynamically, the exact solution (with sounds even!) is here: https://stackoverflow.com/a/7182576/9274948
Side note: your switch (apiException.getStatusCode()) {
does not make much sense, just use apiException.getStatusCode().name()
or apiException.getStatusCode().toString()
.