无法从LocationListener的获得当前位置 [英] Unable to get current location from LocationListener

查看:182
本文介绍了无法从LocationListener的获得当前位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 LocationService 这将启动 onResume() MainActivity 和停止的onDestroy()

  @覆盖
保护无效onResume(){
    super.onResume();
    //使用alaram经理启动服务
    //如果它不是当前运行
    如果(isLocationServiceRunning(本)){
        AM =(AlarmManager)getSystemService(ALARM_SERVICE);
        意向意图=新的意图(这一点,LocationService.class);
        PI = PendingIntent.getService(此,0,意向,
                PendingIntent.FLAG_UPDATE_CURRENT);
        am.cancel(PI);
        am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime(),1 * 60 * 1000,圆周率);
    }
}

@覆盖
保护无效的onDestroy(){
    super.onDestroy();
    如果(isLocationServiceRunning(本)){
        stopService(新意图(这一点,LocationService.class));
        如果(我= NULL和放大器;!&安培;!PI = NULL){
            am.cancel(PI);
        }
    }
}
 

LocationService.java

 公共类LocationService扩展服务实现LocationListener的{

    公共静态双curLat = 0.0;
    公共静态双curLng = 0.0;
    私人LocationManager经理;
    私人字符串最好;
    私人的位置定位;
    私人的位置currentBestLocation;
    私有静态最终诠释TWO_MINUTES = 1000 * 60 * 2;

    @覆盖
    公众的IBinder onBind(意向为arg0){
        返回null;
    }

    @覆盖
    公众诠释onStartCommand(意向意图,诠释标志,诠释startId){

        经理=(LocationManager)getSystemService(LOCATION_SERVICE);
        布尔gps_enabled =经理
                .isProviderEnabled(LocationManager.GPS_PROVIDER);

        如果(gps_enabled){

            //如果GPS已启用,设置标准为ACCURACY_FINE
            //并获得最佳供应商(通常会GPS_PROVIDER)
            标准标准=新标准();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);

            最好= mgr.getBestProvider(标准,真正的);
            // getLastKnownLocation使得用户不需要等待
            位置= mgr.getLastKnownLocation(最好);
            如果(位置== NULL){
                //请求单个更新,然后再试一次。
                //后来会要求每10分钟更新
                mgr.requestSingleUpdate(标准,这一点,NULL);
                位置=经理
                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }
            如果(位置!= NULL){
                //如果GPS提供的位置,更新curLat和curLng
                dumpLocation(位置);
            } 其他 {
                //如果该位置仍然空,去NETWORK_PROVIDER
                最好= LocationManager.NETWORK_PROVIDER;
                位置= mgr.getLastKnownLocation(最好);
                如果(位置!= NULL){
                    //如果网络提供的位置,更新curLat和curLng
                    dumpLocation(位置);
                }
            }
            //注册更新位置管理,同时与
            //提供商
            //由于GPS的更新是昂贵的,我们要求更新每个10分钟,
            //注销更新,如果GPS在禁用onProviderDisabled
            // 回电话
            mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    10 * 60 * 1000,50,这一点);
            // NETWORK_PROVIDER更新每隔20秒
            mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    20 * 1000,0,这一点);

            返回START_NOT_STICKY;
        } 其他 {
            //如果GPS是禁用,去NETWORK_PROVIDER
            最好= LocationManager.NETWORK_PROVIDER;
            位置= mgr.getLastKnownLocation(最好);
            如果(位置!= NULL){
                dumpLocation(位置);
            }
            //注册NETWORK_PROVIDER更新每20秒
            mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    20 * 1000,0,这一点);
            返回START_NOT_STICKY;
        }
    }

    私人无效dumpLocation(位置L){
        //调用更新curLat和curLng。
        currentBestLocation =升;
        SimpleDateFormat的S =新的SimpleDateFormat(DD / MM / YYYY HH:MM:SS,
                Locale.ENGLISH);
        字符串格式= s.format(l.getTime());
        尝试 {
            地理codeR codeR =新的地缘codeR(本);
            名单<地址>地址;
            地址位置= NULL;
            地址= coder.getFromLocation(l.getLatitude(),l.getLongitude()
                    1);
            位置= address.get(0);
        }赶上(例外五){
            Log.e(异常同时获得地址,e.getMessage()+);
        }
        curLat = l.getLatitude();
        curLng = l.getLongitude();
    }

    @覆盖
    公共无效onLocationChanged(位置定位){
        //调用时的位置发生了变化,因为我们注册地点
        //提供商
        //更新
        如果(isBetterLocation(位置,currentBestLocation)){
            dumpLocation(位置);
        } 其他 {
            Log.d(不是一个更好的位置,忽略);
        }
    }

    @覆盖
    公共无效onProviderDisabled(字符串提供商){
        //检查最好的(当前正在使用的供应商)不为空
        如果(最好的!= NULL){
            //如果最好和残疾人提供者是一样的,删除更新
            如果((provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER)及&安培;最好
                    .equals(LocationManager.GPS_PROVIDER))
                    ||提供商
                            .equalsIgnoreCase(LocationManager.NETWORK_PROVIDER)
                    &功放;&安培; best.equals(LocationManager.NETWORK_PROVIDER)){
                如果(经理!= NULL){
                    mgr.removeUpdates(本);
                }
            }
        }
    }

    @覆盖
    公共无效onProviderEnabled(字符串提供商){
        //这将是照顾在如果gps_enabled的onStartCommand
        //情况下被使用。
    }

    @覆盖
    公共无效onStatusChanged(字符串商,INT地位,捆绑演员){
        //无需在意,因为像OUT_OF_SERVICE任何事情发生,
        //位置被取出的将是无效和这种情况下,如上处理。
        如果((provider.equals(LocationManager.GPS_PROVIDER))
                &功放;&安培; (LocationProvider.OUT_OF_SERVICE ==状态)){
            如果(经理!= NULL){
                mgr.removeUpdates(本);
            }
        }
    }

    @覆盖
    公共无效的onDestroy(){
        super.onDestroy();
        //当我们调用stopService(LocationService)触发;
        //这是在MainActivity中的onDestroy完成
        //因为LocationService必须停止
        //当应用程序被关闭,以避免数据的使用
        如果(经理!= NULL){
            mgr.removeUpdates(本);
        }
    }

    保护布尔isBetterLocation(地点的位置,
            地点currentBestLocation){
        如果(currentBestLocation == NULL){
            //一个新的位置总是比没有位置更好
            返回true;
        }

        //检查新的位置锁定是否是新还是旧,
        长timeDelta = location.getTime() -  currentBestLocation.getTime();
        布尔isSignificantlyNewer = timeDelta> TWO_MINUTES;
        布尔isSignificantlyOlder = timeDelta< -TWO_MINUTES;
        布尔isNewer = timeDelta> 0;

        //如果它已经超过两分钟,因为当前的位置,使用
        //新位置
        //因为用户可能已经移动
        如果(isSignificantlyNewer){
            返回true;
            //如果新位置是超过两分钟以上,它必须是
            //差
        }否则,如果(isSignificantlyOlder){
            返回false;
        }

        //检查新的位置锁定是否或多或少准确
        INT accuracyDelta =(INT)(location.getAccuracy() -  currentBestLocation
                .getAccuracy());
        布尔isLessAccurate = accuracyDelta> 0;
        布尔isMoreAccurate = accuracyDelta< 0;
        布尔isSignificantlyLessAccurate = accuracyDelta> 200;

        //检查旧的和新的位置都来自同一个供应商
        布尔isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        //不显著更新或以上,所以检查精度
        如果(isMoreAccurate){
            如果//更准确的回归真实
            返回true;
        }否则如果(isNewer&安培;&安培;!isLessAccurate){
            //相同的精度,但较新的,返回true
            返回true;
        }否则如果(isNewer&安培;&安培;!isSignificantlyLessAccurate
                &功放;&安培; isFromSameProvider){
            //精度小于(并不多,虽然),但新的,所以如果从同一
            //提供商还真
            返回true;
        }
        返回false;
    }

    //检查是否两家供应商是相同的
    私人布尔isSameProvider(字符串provider1,字符串Provider2的){
        如果(provider1 == NULL){
            返回Provider2的== NULL;
        }
        返回provider1.equals(Provider2的);
    }
}
 

这项服务肯定启动和停止的预期的,我可以看到在日志中的位置的细节,这是罚款。

的问题,如果当我移动到一个完全不同的位置(300英里),在 curLat curLng 值仍然为旧的,当我打开应用程序。

是不是因为我没有运行该服务时,该设备在运动(因为我的应用程序没有运行)?

由于当我打开其他应用程序,如四角(它得到正确的位置),然后重新打开我的应用程序,那么它显示了正确的位置。

还有哪些我应该做的正确的刷新位置。

解决方案

我觉得你的问题是在这里

 最佳= mgr.getBestProvider(标准,真正的);
// getLastKnownLocation使得用户不需要等待
位置= mgr.getLastKnownLocation(最好);
如果(位置== NULL){
     //请求单个更新,然后再试一次。
     //后来会要求每10分钟更新
     mgr.requestSingleUpdate(标准,这一点,NULL);
     位置=经理
             .getLastKnownLocation(LocationManager.GPS_PROVIDER);
 }
 

因为有previously位置位置= mgr.getLastKnownLocation(最好); 返回该位置的开始提供商(见<一href="http://developer.android.com/reference/android/location/LocationManager.html#getLastKnownLocation%28java.lang.String%29" 。相对=nofollow> Android的文档所以位置是不是null, mgr.requestSingleUpdate(标准,这一点,NULL); 永远不会运行<。 / P>

要获取最新位置数据提供商必须启动。

这样的修正可以是:

 最佳= mgr.getBestProvider(标准,真正的);
// getLastKnownLocation使得用户不需要等待
mgr.requestSingleUpdate(最好的,这一点,NULL);
位置= mgr.getLastKnownLocation(最好);
 

另外,我不知道,如果它的目的,但这一服务将使用网络供应商,即使有GPS数据时,更准确(由于选择了全球定位系统的更新和数据过时10分钟,2分钟次。

P.S。有没有你不希望使用FusedLocationProvider是谷歌的一部分播放服务特定的原因是什么?我发现它是简单,它理应为选定的最佳供应商和节省电池进行了优化。

I have a LocationService which starts onResume() of the MainActivity and stops onDestroy().

@Override
protected void onResume() {
    super.onResume();
    //Start the service using alaram manager
    //If its not running currently
    if (isLocationServiceRunning(this)) {
        am = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent intent = new Intent(this, LocationService.class);
        pi = PendingIntent.getService(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        am.cancel(pi);
        am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime(), 1 * 60 * 1000, pi);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (isLocationServiceRunning(this)) {
        stopService(new Intent(this, LocationService.class));
        if (am != null && pi != null) {
            am.cancel(pi);
        }
    }
}

LocationService.java

public class LocationService extends Service implements LocationListener {

    public static double curLat = 0.0;
    public static double curLng = 0.0;
    private LocationManager mgr;
    private String best;
    private Location location;
    private Location currentBestLocation;
    private static final int TWO_MINUTES = 1000 * 60 * 2;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
        boolean gps_enabled = mgr
                .isProviderEnabled(LocationManager.GPS_PROVIDER);

        if (gps_enabled) {

            // If GPS is enabled, set criteria as ACCURACY_FINE
            // and get the best provider(which usually will be GPS_PROVIDER)
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);

            best = mgr.getBestProvider(criteria, true);
            // getLastKnownLocation so that user don't need to wait
            location = mgr.getLastKnownLocation(best);
            if (location == null) {
                // request for a single update, and try again.
                // Later will request for updates every 10 mins
                mgr.requestSingleUpdate(criteria, this, null);
                location = mgr
                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);
            }
            if (location != null) {
                // If the GPS gives a location, update curLat and curLng
                dumpLocation(location);
            } else {
                // If the location is still null, go for NETWORK_PROVIDER
                best = LocationManager.NETWORK_PROVIDER;
                location = mgr.getLastKnownLocation(best);
                if (location != null) {
                    // If the NETWORK gives a location, update curLat and curLng
                    dumpLocation(location);
                }
            }
            // Register the Location Manager for updates, with both the
            // providers
            // Since GPS updates are expensive, we ask update every 10 mins and
            // unregister updates if GPS is disabled in onProviderDisabled
            // callback
            mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    10 * 60 * 1000, 50, this);
            // NETWORK_PROVIDER updates every 20 secs
            mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    20 * 1000, 0, this);

            return START_NOT_STICKY;
        } else {
            // If GPS is disables, go with NETWORK_PROVIDER
            best = LocationManager.NETWORK_PROVIDER;
            location = mgr.getLastKnownLocation(best);
            if (location != null) {
                dumpLocation(location);
            }
            // Register NETWORK_PROVIDER for updates every 20 secs
            mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    20 * 1000, 0, this);
            return START_NOT_STICKY;
        }
    }

    private void dumpLocation(Location l) {
        // Called to update the curLat and curLng.
        currentBestLocation = l;
        SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss",
                Locale.ENGLISH);
        String format = s.format(l.getTime());
        try {
            Geocoder coder = new Geocoder(this);
            List<Address> address;
            Address location = null;
            address = coder.getFromLocation(l.getLatitude(), l.getLongitude(),
                    1);
            location = address.get(0);
        } catch (Exception e) {
            Log.e("Exception while getting address", e.getMessage() + "");
        }
        curLat = l.getLatitude();
        curLng = l.getLongitude();
    }

    @Override
    public void onLocationChanged(Location location) {
        // called when location is changed, since we registered Location
        // Providers
        // for updates
        if (isBetterLocation(location, currentBestLocation)) {
            dumpLocation(location);
        } else {
            Log.d("Not a Better Location", "Ignore");
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        // Check if best(the currently being used provider) is not null
        if (best != null) {
            // if best and disabled provider are same, the remove updates
            if ((provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER) && best
                    .equals(LocationManager.GPS_PROVIDER))
                    || provider
                            .equalsIgnoreCase(LocationManager.NETWORK_PROVIDER)
                    && best.equals(LocationManager.NETWORK_PROVIDER)) {
                if (mgr != null) {
                    mgr.removeUpdates(this);
                }
            }
        }
    }

    @Override
    public void onProviderEnabled(String provider) {
        // This will be taken care in the onStartCommand where if gps_enabled
        // case is used.
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // No need to care about, because any thing like OUT_OF_SERVICE occurs,
        // location being fetched will be null and such cases are handled above.
        if ((provider.equals(LocationManager.GPS_PROVIDER))
                && (LocationProvider.OUT_OF_SERVICE == status)) {
            if (mgr != null) {
                mgr.removeUpdates(this);
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // triggered when we call stopService(LocationService);
        // which is done in onDestroy of MainActivity
        // Because LocationService must be stopped
        // when application is closed to avoid data usage
        if (mgr != null) {
            mgr.removeUpdates(this);
        }
    }

    protected 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 > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        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
        } else if (isSignificantlyOlder) {
            return false;
        }

        // 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());

        // Not significantly newer or older, so check for Accuracy
        if (isMoreAccurate) {
            // If more accurate return true
            return true;
        } else if (isNewer && !isLessAccurate) {
            // Same accuracy but newer, return true
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate
                && isFromSameProvider) {
            // Accuracy is less (not much though) but is new, so if from same
            // provider return true
            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);
    }
}

The service surely starts and stops as expected and I can see the location details in log, which are fine.

The problem if when I move to a complete different location(300 miles), the curLat and curLng values still remain as that of the old, when I open the application.

Is it because I am not running the service when the device is in motion(because my application is not running)?

Because when I open some other application like FourSquare(which gets the correct location) and then reopen my application, then it shows the correct location.

What else should I do to refresh the location properly.

解决方案

I think your problem is here

best = mgr.getBestProvider(criteria, true);
// getLastKnownLocation so that user don't need to wait
location = mgr.getLastKnownLocation(best);
if (location == null) {
     // request for a single update, and try again.
     // Later will request for updates every 10 mins
     mgr.requestSingleUpdate(criteria, this, null);
     location = mgr
             .getLastKnownLocation(LocationManager.GPS_PROVIDER);
 }

because there was previously a location location = mgr.getLastKnownLocation(best); returns that location without starting the provider (see the android documentation. So the location is not null and mgr.requestSingleUpdate(criteria, this, null); is never run.

To get up to date location data a provider must be started.

so a correction could be:

best = mgr.getBestProvider(criteria, true);
// getLastKnownLocation so that user don't need to wait
mgr.requestSingleUpdate(best, this, null);
location = mgr.getLastKnownLocation(best);

Also I'm not sure if it is intended but this service will use the network provider even when GPS data is available and more accurate (due to the 10 minute and 2 minute times chosen for GPS updates and data obsolescence.

P.S. Is there a specific reason you do not want to use FusedLocationProvider that is part of Google Play Services? I have found it to be simpler and it is supposedly optimized for selected best providers and conserving battery.

这篇关于无法从LocationListener的获得当前位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆