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

Android中LocationListener的onLocationChange()方法无法触发问题

解决索尼Z3 Compact日版(SO-O2G)定位应用onLocationChange()未触发的问题

嘿,我来帮你搞定这个定位监听不触发的问题!既然谷歌地图能正常定位,说明设备硬件和系统定位服务是没问题的,问题大概率出在你的应用代码的权限处理逻辑上,下面是具体的排查和修复方案:

1. 核心问题:缺少权限请求的回调处理

你在onCreate里发起了动态权限请求,但权限请求是异步操作——用户点击授权的时机可能晚于onStart的执行,这时候onStart里的权限检查会失败,导致requestLocationUpdates根本没被调用。必须添加onRequestPermissionsResult回调方法,在用户完成授权后再初始化定位监听:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 0) {
        // 只要有一个定位权限被授予,就尝试启动定位监听
        boolean hasLocationPermission = false;
        for (int result : grantResults) {
            if (result == PackageManager.PERMISSION_GRANTED) {
                hasLocationPermission = true;
                break;
            }
        }
        if (hasLocationPermission && locationManager != null) {
            try {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
                Toast.makeText(this, "定位监听已启动", Toast.LENGTH_SHORT).show();
            } catch (SecurityException e) {
                Log.e("LocationError", "权限异常: " + e.getMessage());
            }
        } else {
            Toast.makeText(this, "需要定位权限才能获取位置", Toast.LENGTH_SHORT).show();
        }
    }
}

2. 调整权限判断逻辑(过于严格的条件)

你在onStart里的判断要求同时拥有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION权限才会启动定位,但实际上ACCESS_FINE_LOCATION已经包含了ACCESS_COARSE_LOCATION的权限范围,只要有其中一个权限就可以正常请求定位更新。修改后的onStart方法:

@Override
protected void onStart() {
    super.onStart();
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (locationManager != null) {
        // 只要有一个定位权限被授予就执行
        boolean hasFinePermission = ContextCompat.checkSelfPermission(this, PERMISSION_ONE) == PackageManager.PERMISSION_GRANTED;
        boolean hasCoarsePermission = ContextCompat.checkSelfPermission(this, PERMISSION_TWO) == PackageManager.PERMISSION_GRANTED;
        if (hasFinePermission || hasCoarsePermission) {
            try {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
                Log.i("LocationInit", "已启动定位监听");
            } catch (SecurityException e) {
                Log.e("LocationError", "启动监听失败: " + e.getMessage());
            }
        } else {
            Toast.makeText(this, "权限未授予", Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(this, "无法获取定位服务", Toast.LENGTH_SHORT).show();
    }
    periodicallyCheck();
}

3. 额外的排查与验证点

  • 检查应用权限设置:进入设备的「设置-应用-你的应用-权限」,确认「位置」权限已经被授予(有时候动态权限请求可能被用户误拒,或者系统默认未开启)。
  • 测试环境适配:室内环境下GPS定位可能需要较长时间,你可以先关闭GPS_PROVIDER的请求,单独测试NETWORK_PROVIDER(确保移动数据或Wi-Fi已开启),看是否能触发onLocationChange。
  • 日志排查:在权限检查和requestLocationUpdates的位置添加日志,确认代码是否走到了对应的逻辑块——比如在onStart的权限判断分支打印Log,明确是进入了授权分支还是未授权分支。

修复后的完整MainActivity代码

package com.testingpurpose;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private LocationManager locationManager;
    private Location lastLocation;
    private double distanceIntoMeters;
    private final String PERMISSION_ONE = Manifest.permission.ACCESS_FINE_LOCATION;
    private final String PERMISSION_TWO = Manifest.permission.ACCESS_COARSE_LOCATION;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ContextCompat.checkSelfPermission(this, PERMISSION_ONE) != PackageManager.PERMISSION_GRANTED && 
            ContextCompat.checkSelfPermission(this, PERMISSION_TWO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{PERMISSION_ONE, PERMISSION_TWO}, 0);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (locationManager != null) {
            boolean hasFinePermission = ContextCompat.checkSelfPermission(this, PERMISSION_ONE) == PackageManager.PERMISSION_GRANTED;
            boolean hasCoarsePermission = ContextCompat.checkSelfPermission(this, PERMISSION_TWO) == PackageManager.PERMISSION_GRANTED;
            if (hasFinePermission || hasCoarsePermission) {
                try {
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
                    Log.i("LocationInit", "已启动定位监听");
                } catch (SecurityException e) {
                    Log.e("LocationError", "启动监听失败: " + e.getMessage());
                }
            } else {
                Toast.makeText(this, "权限未授予", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(this, "无法获取定位服务", Toast.LENGTH_SHORT).show();
        }
        periodicallyCheck();
    }

    void periodicallyCheck(){
        final Handler handler = new Handler();
        final TextView tv = findViewById(R.id.tv);
        handler.post(new Runnable() {
            @Override
            public void run() {
                String format = String.format("%.2f %s",distanceIntoMeters,"meters");
                tv.setText(format);
                handler.postDelayed(this,1000);
            }
        });
    }

    private LocationListener listener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Log.i("Location Updates: ",">>> Lat "+location.getLatitude()+" , >>> Long "+location.getLongitude());
            if ( lastLocation == null ){
                lastLocation = location;
                return;
            }
            distanceIntoMeters += location.distanceTo(lastLocation);
            lastLocation = location;
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {}

        @Override
        public void onProviderEnabled(String provider) {}

        @Override
        public void onProviderDisabled(String provider) {}
    };

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 0) {
            boolean hasLocationPermission = false;
            for (int result : grantResults) {
                if (result == PackageManager.PERMISSION_GRANTED) {
                    hasLocationPermission = true;
                    break;
                }
            }
            if (hasLocationPermission && locationManager != null) {
                try {
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
                    Toast.makeText(this, "定位监听已启动", Toast.LENGTH_SHORT).show();
                } catch (SecurityException e) {
                    Log.e("LocationError", "权限异常: " + e.getMessage());
                }
            } else {
                Toast.makeText(this, "需要定位权限才能获取位置", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (locationManager != null && listener != null){
            locationManager.removeUpdates(listener);
        }
    }
}

另外,你的activity_main.xml代码不完整,只需补全TextView的layout_height属性为wrap_content即可,不影响定位逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:35:43