Android onLocationChanged 不调用

Posted

技术标签:

【中文标题】Android onLocationChanged 不调用【英文标题】:Android onLocationChanged does not called 【发布时间】:2017-08-07 18:19:21 【问题描述】:

我正在尝试使用 Service 和 LocationListener 在 android 中实现后台 GPS 定位服务。服务已启动(-> 调用了 onCreate 和 onStartCommand 方法),但从未调用过 onLocationChanged 方法。

这是我的服务的代码:

public class GpsHandler extends Service implements LocationListener
private static final String TAG = "GpsHandler";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private final String LOCATION_BROADCAST_TAG = "android.LOCATION";
private final String LOCATION_EXTRA_TAG = "Location";
private Location mLastLocation = null;
@Nullable
@Override
public IBinder onBind(Intent intent) 
    return null;

@Override
public void onCreate()

    Toast.makeText(this, "Service Started, onCreate", Toast.LENGTH_LONG).show();

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    // Let it continue running until it is stopped.

    Toast.makeText(this, "Service Started, onStartCommand", Toast.LENGTH_LONG).show();
    if (mLocationManager == null)
    
        mLocationManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    
    mLastLocation = new Location(LocationManager.GPS_PROVIDER);
    try 
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, this);
     catch (java.lang.SecurityException ex) 
    Log.i(TAG, "fail to request location update, ignore", ex);
 catch (IllegalArgumentException ex) 
    Log.d(TAG, "gps provider does not exist " + ex.getMessage());

    return START_STICKY;


@Override
public void onDestroy() 
    super.onDestroy();
    if (mLocationManager != null)
    
        try 
            mLocationManager.removeUpdates(this);
         catch (Exception ex) 
            Log.i(TAG, "fail to remove location listners, ignore", ex);
        
    
    Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();

@Override
public void onProviderDisabled(String provider) 

    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(intent);
    Toast.makeText(getBaseContext(), "Gps is turned off!! ",
            Toast.LENGTH_SHORT).show();

@Override
public void onLocationChanged(Location location)

    Toast.makeText(this, "Location Changed", Toast.LENGTH_LONG).show();
    if(isBetterLocation(location,mLastLocation))
    
        mLastLocation.set(location);
        Intent intent = new Intent(LOCATION_BROADCAST_TAG).putExtra(LOCATION_EXTRA_TAG, location);
        sendBroadcast(intent);
    


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

private boolean isBetterLocation(Location location, Location currentBestLocation) 
    if (currentBestLocation == null) 
        // A new location is always better than no location
        return true;
    
    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > 1000*30;//30000ms = 30 sec
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location
    // because the user has likely moved
    if (isSignificantlyNewer)
    
        return true;
        // If the new location is more than two minutes older, it must be worse
    

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
            currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) 
        return true;
     else if (isNewer && !isLessAccurate) 
        return true;
     else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) 
        return true;
    
    return false;

/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) 
    if (provider1 == null) 
        return provider2 == null;
    
    return provider1.equals(provider2);

【问题讨论】:

我赌“请求位置更新失败,忽略” 不,这是安卓模拟器的错。现在它可以工作了。 【参考方案1】:

我终于找到了解决方案。我曾尝试使用其他模拟器(最初我使用的是 Pixel C 模拟器)对其进行调试,现在它可以完美运行。所以这只是一个 Studio Bug,代码是可以工作的。我也对代码做了一点重构,去掉了一些无用的功能:

工作代码:

public class GpsHandler extends Service implements LocationListener
private static final String TAG = "GpsHandler";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0f;
private final String LOCATION_BROADCAST_TAG = "android.LOCATION";
private final String LOCATION_EXTRA_TAG = "Location";
private Location mLastLocation = null;
@Nullable
@Override
public IBinder onBind(Intent intent) 
    return null;

@Override
public void onCreate()

    Toast.makeText(this, "Service Started, onCreate", Toast.LENGTH_LONG).show();

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    // Let it continue running until it is stopped.

    Toast.makeText(this, "Service Started, onStartCommand", Toast.LENGTH_LONG).show();
    if (mLocationManager == null)
    
        mLocationManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    
    mLastLocation = new Location(LocationManager.GPS_PROVIDER);
    try 
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, this);
        mLastLocation.set(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
     catch (java.lang.SecurityException ex) 
    Log.i(TAG, "fail to request location update, ignore", ex);
 catch (IllegalArgumentException ex) 
    Log.d(TAG, "gps provider does not exist " + ex.getMessage());

    return START_STICKY;


@Override
public void onDestroy() 
    super.onDestroy();
    if (mLocationManager != null)
    
        try 
            mLocationManager.removeUpdates(this);
         catch (Exception ex) 
            Log.i(TAG, "fail to remove location listners, ignore", ex);
        
    
    Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();

@Override
public void onProviderDisabled(String provider) 

    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(intent);
    Toast.makeText(getBaseContext(), "Gps is turned off!! ",
            Toast.LENGTH_SHORT).show();

@Override
public void onLocationChanged(Location location)

    Toast.makeText(this, "Location Changed", Toast.LENGTH_LONG).show();
    if(location.getAccuracy()<4*mLastLocation.getAccuracy())
    
        mLastLocation.set(location);
        Intent intent = new Intent(LOCATION_BROADCAST_TAG).putExtra(LOCATION_EXTRA_TAG, location);
        sendBroadcast(intent);
    

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

【讨论】:

以上是关于Android onLocationChanged 不调用的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中未调用 onlocationchanged

为啥 Android 服务中没有调用 OnlocationChanged?

Android onLocationChanged 不调用

Android OnlocationChanged storage

android - 即使没有可用的互联网,也会调用 onLocationChanged

Android Google Maps API OnLocationChanged 仅调用一次