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

Android Studio应用中位置信息返回null的原因排查

位置信息始终返回null但Activity Recognition正常的问题排查与解决

在Android Studio开发的应用中,我们实现了Activity Recognition与位置检测功能,发现latitude、longitude和speed始终返回null,但Activity Recognition功能可正常返回结果,且已在Manifest中配置所有相关权限。

相关代码

ActivityRecognitionService类

public class ActivityRecognitionService extends Service {
    //通知渠道常量
    private static final int NOTIFICATION_ID = 1;
    private static final String CHANNEL_ID = "ActivityRecognitionChannel";

    //位置识别相关变量
    private String latitude;
    private String longitude;
    private String speed;

    LocationCallback mLocationCallback;

    @Override
    @SuppressLint("MissingPermission")
    public void onCreate() {
        super.onCreate();

        LocationRequest mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(2000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                for (Location location : locationResult.getLocations()) {
                    if (location != null) {
                        latitude = String.valueOf(location.getLatitude());
                        longitude = String.valueOf(location.getLongitude());
                        speed = String.valueOf(location.getSpeed());
                    } else {
                        Log.d("Location", "Location not available");
                    }
                }
            }
        };
        LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, mLocationCallback, null);

        //创建通知渠道
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Activity Recognition Channel", NotificationManager.IMPORTANCE_HIGH);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
    }

    //服务启动时调用,负责启动AR功能
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(NOTIFICATION_ID, createNotification());
        new Thread(
                this::startActivityRecognition
        ).start();
        return START_STICKY;
    }

    //服务销毁时执行
    @Override
    public void onDestroy() {
        super.onDestroy();
        stopActivityRecognition();
    }

    //启动AR功能
    @SuppressLint("MissingPermission") //权限已提前申请并校验
    private void startActivityRecognition() {
        ActivityRecognitionClient activityRecognitionClient = ActivityRecognition.getClient(this);
        Task<Void> task = activityRecognitionClient.requestActivityUpdates(2000, getActivityRecognitionPendingIntent());

        task.addOnSuccessListener(
                success -> Log.d("ActivityRecognition", "Start activity recognition!")
        );

        task.addOnFailureListener(
                error -> Log.e("ActivityRecognition", "Start activity recognition failed!")
        );

        LocationServices.getFusedLocationProviderClient(this)
                .getLastLocation()
                .addOnSuccessListener(location -> {
                    if(location != null){
                        latitude = String.valueOf(location.getLatitude());
                        longitude = String.valueOf(location.getLongitude());
                        speed = String.valueOf(location.getSpeed());
                    } else {
                        Log.d("Location", "Location not available");
                    }
                });
    }

    //停止AR功能
    @SuppressLint("MissingPermission") //权限已提前申请并校验
    private void stopActivityRecognition() {
        LocationServices.getFusedLocationProviderClient(this).removeLocationUpdates(mLocationCallback);

        ActivityRecognitionClient activityRecognitionClient = ActivityRecognition.getClient(this);
        Task<Void> task = activityRecognitionClient.removeActivityUpdates(getActivityRecognitionPendingIntent());

        task.addOnSuccessListener(
                success -> Log.d("ActivityRecognition", "Stop activity recognition!")
        );

        task.addOnFailureListener(
                error -> Log.e("ActivityRecognition", "Stop activity recognition failed!")
        );
    }

    //为ActivityRecognition传递Intent
    @SuppressLint("MissingPermission")
    private PendingIntent getActivityRecognitionPendingIntent() {
        Intent intent = new Intent(this, ActivityTransitionsReceiver.class);
        intent.putExtra("Latitude", latitude);
        intent.putExtra("Longitude", longitude);
        intent.putExtra("Speed", speed);
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_MUTABLE);
    }

    //创建并显示状态栏通知
    @SuppressLint("MissingPermission") //权限已提前申请并校验
    private Notification createNotification() {
        Intent notificationIntent = new Intent(this, HomeActivity.class);
        notificationIntent.setAction(Intent.ACTION_MAIN);
        notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Activity Recognition Service")
                .setContentText("Running...")
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.drawable.ic_notification)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(false)
                .setOngoing(true)
                .build();

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(NOTIFICATION_ID, notification);

        return notification;
    }

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

ActivityTransitionsReceiver类

public class ActivityTransitionsReceiver extends IntentService {

    public ActivityTransitionsReceiver() {
        super("ActivityRecognitionService");
    }


    //接收包含识别到的活动的Intent
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            String latitude = intent.getStringExtra("Latitude");
            String longitude = intent.getStringExtra("Longitude");
            String speed = intent.getStringExtra("Speed");
            if (ActivityRecognitionResult.hasResult(intent)) {
                ActivityRecognitionResult activityResult = ActivityRecognitionResult.extractResult(intent);
                if (activityResult != null) {
                    handleActivityRecognitionResult(activityResult, latitude, longitude, speed);
                }
            }
        }
    }

    //处理识别到的活动
    @SuppressLint("MissingPermission") //权限已提前申请并校验
    private void handleActivityRecognitionResult(ActivityRecognitionResult activityResult, String latitude, String longitude, String speed) {
        DetectedActivity mostProbableActivity = activityResult.getMostProbableActivity();
        int confidence = mostProbableActivity.getConfidence();
        int activityType = mostProbableActivity.getType();

        Log.i("AR", "Activity detected: " + getActivityName(activityType) + "/" + confidence + "\nLatitude: " + latitude + "\nLongitude: " + longitude + "\nSpeed: " + speed);
    }

    //获取识别到的活动名称
    private String getActivityName(int activityType) {
        switch (activityType) {
            case DetectedActivity.IN_VEHICLE:
                return "In vehicle";
            case DetectedActivity.ON_BICYCLE:
                return "On bicycle";
            case DetectedActivity.ON_FOOT:
                return "On foot";
            case DetectedActivity.RUNNING:
                return "Running";
            case DetectedActivity.STILL:
                return "Still";
            case DetectedActivity.TILTING:
                return "Tilting";
            case DetectedActivity.WALKING:
                return "Walking";
            case DetectedActivity.UNKNOWN:
                return "Unknown";
            default:
                return "Undefined";
        }
    }
}

问题原因分析

  1. PendingIntent初始化时机错误:getActivityRecognitionPendingIntent()在启动Activity Recognition时被调用,此时位置信息还未获取到(getLastLocation()或LocationCallback的回调可能还未执行),导致Intent的Extra参数都是初始null值。且PendingIntent一旦创建,若不主动更新,内部的Extra不会自动同步后续的变量变化。
  2. 位置更新与数据传递不同步:LocationCallback中更新了latitude等变量,但这些变量不会自动同步到已创建的PendingIntent中,Activity Recognition触发时传递的仍是最初的null值。
  3. getLastLocation()的不确定性:该方法返回设备最后一次缓存的位置,若设备长时间未获取位置或缓存失效,会返回null,无法依赖它作为唯一位置来源。

解决方案

方案一:位置更新时重新创建PendingIntent

每次LocationCallback获取到新位置后,重新注册Activity Recognition,用更新后的位置信息创建新的PendingIntent替换旧的:

修改onLocationResult方法:

@Override
public void onLocationResult(LocationResult locationResult) {
    for (Location location : locationResult.getLocations()) {
        if (location != null) {
            latitude = String.valueOf(location.getLatitude());
            longitude = String.valueOf(location.getLongitude());
            speed = String.valueOf(location.getSpeed());
            // 位置更新后,重新注册Activity Recognition以更新PendingIntent
            updateActivityRecognitionPendingIntent();
        } else {
            Log.d("Location", "Location not available");
        }
    }
}

添加updateActivityRecognitionPendingIntent方法:

@SuppressLint("MissingPermission")
private void updateActivityRecognitionPendingIntent() {
    ActivityRecognitionClient activityRecognitionClient = ActivityRecognition.getClient(this);
    // 先移除旧的PendingIntent
    activityRecognitionClient.removeActivityUpdates(getActivityRecognitionPendingIntent())
            .addOnSuccessListener(unused -> {
                // 注册新的PendingIntent,此时位置信息已更新
                activityRecognitionClient.requestActivityUpdates(2000, getActivityRecognitionPendingIntent())
                        .addOnSuccessListener(success -> Log.d("ActivityRecognition", "Updated activity recognition pending intent!"))
                        .addOnFailureListener(error -> Log.e("ActivityRecognition", "Failed to update activity recognition pending intent!"));
            })
            .addOnFailureListener(error -> Log.e("ActivityRecognition", "Failed to remove old activity updates!"));
}

方案二:在Receiver中实时获取位置

不在PendingIntent中传递位置信息,而是在Activity识别触发时直接调用FusedLocationProvider获取最新位置,保证每次拿到的都是当前最新数据:

修改ActivityTransitionsReceiver的handleActivityRecognitionResult方法:

@SuppressLint("MissingPermission")
private void handleActivityRecognitionResult(ActivityRecognitionResult activityResult) {
    DetectedActivity mostProbableActivity = activityResult.getMostProbableActivity();
    int confidence = mostProbableActivity.getConfidence();
    int activityType = mostProbableActivity.getType();

    // 实时获取最新位置
    LocationServices.getFusedLocationProviderClient(this)
            .getLastLocation()
            .addOnSuccessListener(location -> {
                String latitude = null;
                String longitude = null;
                String speed = null;
                if (location != null) {
                    latitude = String.valueOf(location.getLatitude());
                    longitude = String.valueOf(location.getLongitude());
                    speed = String.valueOf(location.getSpeed());
                } else {
                    Log.d("Location", "Location not available");
                }
                Log.i("AR", "Activity detected: " + getActivityName(activityType) + "/" + confidence + "\nLatitude: " + latitude + "\nLongitude: " + longitude + "\nSpeed: " + speed);
            })
            .addOnFailureListener(e -> Log.e("Location", "Failed to get location", e));
}

修改onHandleIntent方法,不再传递位置参数:

@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        if (ActivityRecognitionResult.hasResult(intent)) {
            ActivityRecognitionResult activityResult = ActivityRecognitionResult.extractResult(intent);
            if (activityResult != null) {
                handleActivityRecognitionResult(activityResult);
            }
        }
    }
}

简化getActivityRecognitionPendingIntent方法:

private PendingIntent getActivityRecognitionPendingIntent() {
    Intent intent = new Intent(this, ActivityTransitionsReceiver.class);
    return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_MUTABLE);
}

额外优化建议

  • 确认运行时权限:Android 6.0+需动态申请ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION(位置权限)和ACTIVITY_RECOGNITION(Activity识别权限),确保用户已授权。
  • 调整LocationRequest参数:setInterval(2000)间隔过短会增加耗电,建议根据需求调整为5000ms或更长。
  • 监听位置可用性:在LocationCallback中重写onLocationAvailability方法,处理位置不可用的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:32:08