是什么让Android中,用户的当前位置的最简单,最可靠的方法?当前位置、最简单、最可靠、方法

2023-09-11 10:18:15 作者:第一步

在Android上的LocationManager API好像它是一个有点痛苦的使用对于只需要用户的位置,偶尔和粗糙逼近的应用程序。

The LocationManager API in android seems like it's a bit of a pain to use for an application that only needs an occasional and rough approximation of the user's location.

该应用程序我的工作是不是一个真正的位置,应用程序本身,但它确实需要获得以显示附近商家的列表,用户的位置。它并不需要担心,如果用户正在走动或类似的东西。

The app I'm working on isn't really a location app per se, but it does need to get the user's location in order to display a list of nearby businesses. It doesn't need to worry about if the user is moving around or anything like that.

这就是我想要做的:

显示用户附近的位置的列表。 preLOAD用户的位置,这样的时候,我需要它在活动X,这将是可用的。 请不要特别在意的准确性或更新的频率。只要抓住一个位置就足够了,只要它不是路要走。也许,如果我想成为看上我会更新的位置每隔数分钟左右的时间,但它不是一个巨大的任务。 在任何设备的工作,只要有任何一个GPS或网络位置提供者。

现在看来似乎不应该是很难的,但在我看来,我有旋转了两个不同的位置提供商(全球定位系统和网络)和管理每一个生命周期。不仅如此,但我要重复相同的code多项活动,以满足#2。我已经在过去使用getBestProvider()削减解下来只使用一个位置提供试过,但似乎只给你最好的理论提供者,而不是供应商,实际上要给你最好的结果。

It seems like it shouldn't be that hard, but it appears to me that I have to spin up two different location providers (GPS and NETWORK) and manage each's lifecycle. Not only that, but I have to duplicate the same code in multiple activities to satisfy #2. I've tried using getBestProvider() in the past to cut the solution down to just using one location provider, but that seems to only give you the best "theoretical" provider rather than the provider that's actually going to give you the best results.

有没有一种简单的方法来做到这一点?

Is there a simpler way to accomplish this?

推荐答案

下面是我做的:

首先我检查什么启用提供商。有些人可能会在设备上禁用,有些可能会在应用程序清单中被禁用。 如果任何供应商可我开始位置的听众和超时定时器。这是20秒我的例子,可能没有足够的GPS,所以你可以放大。 如果我得到位置监听器更新我使用所提供的价值。我停止监听器和定时器。 如果我没有得到任何更新,计时器到期我不得不使用最后一个已知的值。 我抓住从可用的提供者最后已知值并选择最近的人。

下面是如何使用我的类:

Here's how I use my class:

LocationResult locationResult = new LocationResult(){
    @Override
    public void gotLocation(Location location){
        //Got the location!
    }
};
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);

而这里的MyLocation类:

And here's MyLocation class:

import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled=false;
    boolean network_enabled=false;

    public boolean getLocation(Context context, LocationResult result)
    {
        //I use LocationResult callback class to pass location value from MyLocation to user code.
        locationResult=result;
        if(lm==null)
            lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        //exceptions will be thrown if provider is not permitted.
        try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
        try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}

        //don't start listeners if no provider is enabled
        if(!gps_enabled && !network_enabled)
            return false;

        if(gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
        if(network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
        timer1=new Timer();
        timer1.schedule(new GetLastLocation(), 20000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
             lm.removeUpdates(locationListenerGps);
             lm.removeUpdates(locationListenerNetwork);

             Location net_loc=null, gps_loc=null;
             if(gps_enabled)
                 gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
             if(network_enabled)
                 net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

             //if there are both values use the latest one
             if(gps_loc!=null && net_loc!=null){
                 if(gps_loc.getTime()>net_loc.getTime())
                     locationResult.gotLocation(gps_loc);
                 else
                     locationResult.gotLocation(net_loc);
                 return;
             }

             if(gps_loc!=null){
                 locationResult.gotLocation(gps_loc);
                 return;
             }
             if(net_loc!=null){
                 locationResult.gotLocation(net_loc);
                 return;
             }
             locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult{
        public abstract void gotLocation(Location location);
    }
}

有人可能还希望修改我的逻辑。例如,如果你从网络提供商处获取更新不停止的听众而是继续等待。 GPS提供了更准确的数据,所以这是值得等待的。如果计时器到期,你已经有了更新的网络而不是从GPS那么你可以使用从网络提供的值。

Somebody may also want to modify my logic. For example if you get update from Network provider don't stop listeners but continue waiting. GPS gives more accurate data so it's worth waiting for it. If timer elapses and you've got update from Network but not from GPS then you can use value provided from Network.

一个更方法是使用LocationClient http://developer.android.com/training/location/retrieve-current.html.但是,它需要谷歌播放服务的apk将用户设备上安装。

One more approach is to use LocationClient http://developer.android.com/training/location/retrieve-current.html. But it requires Google Play Services apk to be installed on user device.