Android定位服务广播数据未传递,LatLng对象赋值失败求助
问题分析与解决方案
看起来你的Google Map位置追踪应用遇到了两个核心问题:Service代码未执行,以及因currentLocation为null导致的LatLng初始化失败。我来帮你一步步排查修复:
一、先解决最紧急的NullPointerException问题
你的onResume方法里有一行代码会直接触发空指针异常:
Log.d(TAG, "onResume:"+ currentLocation.toString());
currentLocation初始值是null,在收到Service的广播前调用toString()会直接崩溃,导致后续的广播接收器注册逻辑都无法执行。先修改这行代码:
Log.d(TAG, "onResume:"+ (currentLocation != null ? currentLocation.toString() : "currentLocation is null"));
二、修复Service无法启动/执行的核心原因
1. 修正Activity onCreate的初始化顺序
你当前的onCreate逻辑有问题:如果isServicesOK()返回false,super.onCreate()和setContentView都不会执行,导致Activity上下文初始化失败,后续的startMyService()自然也无法正常工作。正确的顺序应该是:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); if (!isServicesOK()) { Toast.makeText(this, "Google Play Services不可用,请检查后重试", Toast.LENGTH_LONG).show(); finish(); return; } getLocationPermission(); startMyService(); }
2. 适配Android 8.0+的后台Service限制
Android 8.0(API 26)及以上版本对后台Service有严格限制,普通后台Service会被系统快速回收。你需要:
- 在
AndroidManifest.xml中添加前台服务权限:<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> - 在
MyService的onCreate方法中启动前台服务(必须显示一个通知):if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("location_track", "位置追踪", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, "location_track") .setContentTitle("正在追踪位置") .setContentText("应用正在后台获取你的位置") .setSmallIcon(R.drawable.ic_launcher_foreground) .build(); startForeground(1, notification); }
3. 确保Service在Manifest中注册
检查AndroidManifest.xml是否添加了MyService的注册声明,放在<application>标签内:
<service android:name=".MyService" />
三、完善位置接收与地图更新逻辑
在广播接收器收到位置后,不仅要赋值currentLocation,还要直接更新地图(避免onMapReady时位置还未收到):
mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive: 收到位置数据"); Double latitude = (Double) intent.getExtras().get("latitude"); Double longitude = (Double) intent.getExtras().get("longitude"); if (latitude != null && longitude != null) { currentLocation = new LatLng(latitude, longitude); // 收到位置后立即更新地图 if (mMap != null) { moveCamera(currentLocation, DEFAULT_ZOOM); } } else { Log.d(TAG, "onReceive: 经纬度数据为空"); } } };
四、MyService的完整实现参考(你可能缺失的部分)
如果你的MyService还没有正确实现位置获取逻辑,这里提供一个基础版本:
public class MyService extends Service { private static final String TAG = "MyService"; private FusedLocationProviderClient mFusedLocationClient; private LocationCallback mLocationCallback; @Override public void onCreate() { super.onCreate(); mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 初始化位置回调 mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult == null) { Log.d(TAG, "onLocationResult: 位置数据为空"); return; } for (Location location : locationResult.getLocations()) { // 发送广播给Activity Intent intent = new Intent("location"); intent.putExtra("latitude", location.getLatitude()); intent.putExtra("longitude", location.getLongitude()); sendBroadcast(intent); } } }; // 启动前台服务(适配Android 8.0+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("location_track", "位置追踪", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, "location_track") .setContentTitle("正在追踪位置") .setContentText("应用正在后台获取你的位置") .setSmallIcon(R.drawable.ic_launcher_foreground) .build(); startForeground(1, notification); } // 开始请求位置更新 requestLocationUpdates(); } private void requestLocationUpdates() { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setInterval(10000); // 10秒更新一次 locationRequest.setFastestInterval(5000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { stopSelf(); return; } mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.getMainLooper()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; // 服务被杀死后尝试重启 } @Override public void onDestroy() { super.onDestroy(); if (mFusedLocationClient != null && mLocationCallback != null) { mFusedLocationClient.removeLocationUpdates(mLocationCallback); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
最后需要检查的点
- 确保测试设备的位置服务已开启(GPS或网络定位);
- 确认用户已经授予应用位置权限(在系统设置中检查);
- Android 10+版本需要额外申请
ACCESS_BACKGROUND_LOCATION权限,记得在Manifest中添加并在Activity中申请。
内容的提问来源于stack exchange,提问作者Danail Mihalkov
相关产品推荐
相关产品推荐

