You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将LocationService位置数据传递到MainActivity的Azure Maps并实时更新

实现LocationService向Azure Maps实时传递位置信息

问题背景

已开发LocationService,可通过Toast展示当前位置,但无法将位置信息传递至Activity中的Azure Maps实现实时更新。现有LocationService核心代码如下:

@Override
public void onCreate() {
    super.onCreate();

    new Notification();

    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) createNotificationChanel() ;
    else startForeground(
            1,
            new Notification()
    );

    locationRequest = LocationRequest.create();
    locationRequest.setInterval(3000);
    locationRequest.setFastestInterval(3000);
    locationRequest.setMaxWaitTime(5000);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(@NonNull LocationResult locationResult) {
            Location location =  locationResult.getLastLocation();
            Toast.makeText(getApplicationContext(),
                    "Lat: "+Double.toString(location.getLatitude()) + '\n' +
                            "Long: " + Double.toString(location.getLongitude()), Toast.LENGTH_LONG).show();

            currentCoor = new LLcoor(location.getLongitude(), location.getLatitude());

            //locationArrayList.add(new LatLng(location.getLatitude(), location.getLongitude()));

           /* for (Location location : locationResult.getLocations()) {
              location
            }*/
        }
    };
    startLocationUpdates();
}

完整LocationService类代码:

public class LocationService extends Service {
    public static ArrayList<LatLng> locationArrayList = new ArrayList<LatLng>();

    FusedLocationProviderClient fusedLocationClient;
    LocationRequest locationRequest;
    LocationCallback locationCallback;
    LLcoor currentCoor;

    private void startLocationUpdates() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        fusedLocationClient.requestLocationUpdates(locationRequest,
                locationCallback,
                Looper.getMainLooper());
    }

    protected void createLocationRequest() {
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(3000);
        locationRequest.setFastestInterval(5000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        new Notification();

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) createNotificationChanel() ;
        else startForeground(
                1,
                new Notification()
        );

        locationRequest = LocationRequest.create();
        locationRequest.setInterval(3000);
        locationRequest.setFastestInterval(3000);
        locationRequest.setMaxWaitTime(5000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                Location location =  locationResult.getLastLocation();
                Toast.makeText(getApplicationContext(),
                        "Lat: "+Double.toString(location.getLatitude()) + '\n' +
                                "Long: " + Double.toString(location.getLongitude()), Toast.LENGTH_LONG).show();

                currentCoor = new LLcoor(location.getLongitude(), location.getLatitude());

                //locationArrayList.add(new LatLng(location.getLatitude(), location.getLongitude()));

               /* for (Location location : locationResult.getLocations()) {
                  location
                }*/
            }
        };
        startLocationUpdates();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createNotificationChanel() {
        String notificationChannelId = "Location channel id";
        String channelName = "Background Service";

        NotificationChannel chan = new NotificationChannel(
                notificationChannelId,
                channelName,
                NotificationManager.IMPORTANCE_NONE
        );
        chan.setLightColor(Color.BLUE);
        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);

        NotificationManager manager = getSystemService(NotificationManager.class);

        manager.createNotificationChannel(chan);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, notificationChannelId);

        Notification notification = notificationBuilder.setOngoing(true)
                .setContentTitle("Location updates:")
                .setPriority(NotificationManager.IMPORTANCE_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(2, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        fusedLocationClient.removeLocationUpdates(locationCallback);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

解决方案

通过LocalBroadcastManager实现Service与Activity的通信,将位置数据实时传递到Azure Maps。

步骤1:修改LocationService,发送位置广播

在LocationService的onLocationResult方法中添加广播发送逻辑,传递经纬度数据:

// 先导入依赖
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

// 修改locationCallback逻辑
locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(@NonNull LocationResult locationResult) {
        Location location =  locationResult.getLastLocation();
        if (location == null) return; // 避免空指针
        
        Toast.makeText(getApplicationContext(),
                "Lat: "+Double.toString(location.getLatitude()) + '\n' +
                        "Long: " + Double.toString(location.getLongitude()), Toast.LENGTH_LONG).show();

        currentCoor = new LLcoor(location.getLongitude(), location.getLatitude());

        // 发送位置更新广播
        Intent intent = new Intent("LOCATION_UPDATE_ACTION");
        intent.putExtra("LATITUDE", location.getLatitude());
        intent.putExtra("LONGITUDE", location.getLongitude());
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
    }
};

步骤2:在Activity中注册广播接收器,更新Azure Maps

2.1 定义广播接收器

在承载地图的Activity内部添加接收器:

private BroadcastReceiver locationUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("LOCATION_UPDATE_ACTION".equals(intent.getAction())) {
            double latitude = intent.getDoubleExtra("LATITUDE", 0.0);
            double longitude = intent.getDoubleExtra("LONGITUDE", 0.0);
            
            // 触发地图更新
            updateAzureMap(latitude, longitude);
        }
    }
};

2.2 实现地图更新逻辑

编写updateAzureMap方法,完成地图中心移动、位置标记更新:

private void updateAzureMap(double latitude, double longitude) {
    AzureMapControl mapControl = findViewById(R.id.mapControl);
    
    mapControl.onReady(map -> {
        // 创建当前位置坐标点
        com.microsoft.azure.maps.mapcontrol.data.Position position = 
            com.microsoft.azure.maps.mapcontrol.data.Position.fromLatLng(latitude, longitude);
        
        // 移动地图中心到当前位置,设置缩放级别
        map.setCamera(CameraUpdateFactory.newPositionZoom(position, 15));
        
        // 可选:更新当前位置标记
        // 清除旧标记层
        map.getLayers().removeAll(map.getLayers().stream()
            .filter(layer -> layer instanceof SymbolLayer && layer.getId().equals("currentLocationLayer"))
            .collect(Collectors.toList()));
        
        // 创建新标记
        DataSource dataSource = new DataSource();
        map.sources.add(dataSource);
        dataSource.add(Point.fromPosition(position));
        
        SymbolLayer symbolLayer = new SymbolLayer(dataSource, "currentLocationLayer");
        symbolLayer.setIconImage("map-marker-icon"); // 使用内置图标,也可自定义
        map.layers.add(symbolLayer);
    });
}

2.3 注册/注销接收器

在Activity生命周期中管理接收器,避免内存泄漏:

@Override
protected void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter("LOCATION_UPDATE_ACTION");
    LocalBroadcastManager.getInstance(this).registerReceiver(locationUpdateReceiver, filter);
}

@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(locationUpdateReceiver);
}

步骤3:配置依赖与权限

  1. 在app模块build.gradle中添加依赖:
dependencies {
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
    implementation 'com.microsoft.azure.maps:mapcontrol:1.0.0'
}
  1. 在Manifest中声明必要权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

内容的提问来源于stack exchange,提问作者Francisco Torres

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:35:42