当你距离标记 10 米以内时如何开始一些方法?

how to start some method when you come within 10 meters to the marker?

我需要制作带有地图和一些标记的 android 应用程序。当我距离标记 10 米以内时,它变为可点击,点击播放音轨,然后更改标记图标并显示另一个标记。 我尝试使用地理围栏,但我无法更改图标或从 BroadcastReciever 或其他 activity 或服务调用 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, 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:

  1. 您的广播接收器可以是您的 activity 的内部 class 或匿名 class,在这两种情况下,广播接收器都会引用包装 class (MapsActivity.this).
  2. 将上下文作为构造函数参数传递给您的广播接收器。当您希望它成为 top-class 并在多个地方重复使用时很有用。
  3. 在广播接收器的构造函数中传递一个回调(一些FunctionalInterface,f.e。Consumer<Integer> onCheckpointReached)。

按照动态访问特定轨道,你不应该使用这样的开关,而是动态获取资源,确切的解决方案(声音均匀!)在这里:


旁注:您的 switch (apiException.getStatusCode()) { 没有多大意义,只需使用 apiException.getStatusCode().name()apiException.getStatusCode().toString()