问题描述
我需要制作带有地图和一些标记的android应用。当我到达标记的10米以内时,它变得可单击,并在单击时播放音轨,然后更改标记图标并显示另一个标记。 我尝试使用地理围栏,但无法更改图标或从broadcastReciever或其他活动或服务调用MediaPlayer。
标记-地理围栏的中心。
问题:
当地理围栏触发时,如何更改标记的图标并开始音轨?
在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,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,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,Toast.LENGTH_SHORT).show();
case "2":
Toast.makeText(context,Toast.LENGTH_SHORT).show();
case "3":
Toast.makeText(context,Toast.LENGTH_SHORT).show();
case "4":
Toast.makeText(context,Toast.LENGTH_SHORT).show();
case "5":
Toast.makeText(context,Toast.LENGTH_SHORT).show();
}
}
}
解决方法
MediaPlayer需要上下文 好了,您可以将上下文传递给广播接收器。我假设(因为尚未显示)您在上下文的Activity或App中注册了广播接收器。 多种解决方案:
- 您的广播接收者可以是您活动的内部类,也可以是匿名类,在两种情况下,广播接收者都将引用包装类(
MapsActivity.this
)。 - 将Context作为构造函数参数传递给广播接收器。当您希望它成为一流的产品并在多个地方重复使用时很有用。
- 在广播接收器的构造函数中传递回调(某些FunctionalInterface,例如
Consumer<Integer> onCheckpointReached
)。
根据动态访问特定音轨的方法,您不应使用此类开关,而应动态获取资源,确切的解决方案(甚至带有声音!)在这里:https://stackoverflow.com/a/7182576/9274948
旁注:您的switch (apiException.getStatusCode()) {
并没有多大意义,只需使用apiException.getStatusCode().name()
或apiException.getStatusCode().toString()
。