如何将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:配置依赖与权限
- 在app模块
build.gradle中添加依赖:
dependencies { implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' implementation 'com.microsoft.azure.maps:mapcontrol:1.0.0' }
- 在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
相关产品推荐
相关产品推荐

