关于地理定位:在Android上获取用户当前位置的最简单,最强大的方法是什么?

What is the simplest and most robust way to get the user's current location on Android?

android上的LocationManagerAPI对于只需要偶尔粗略估计用户位置的应用程序来说似乎有点麻烦。

我正在开发的应用本身并不是一个定位应用,但它需要获得用户的位置才能显示附近企业的列表。它不需要担心用户是否在移动或类似的事情。

我想做的是:

  • 向用户显示附近位置的列表。
  • 预加载用户的位置,以便我在Activityx中需要它时,它将可用。
  • 我并不特别关心更新的准确性和频率。只要不离得太远,只要抓住一个位置就足够了。如果我想花哨的话,我会每隔几分钟左右更新一次位置,但这不是一个很大的优先事项。
  • 适用于任何设备,只要它有GPS或网络位置提供商。
  • 看起来不应该那么难,但在我看来,我必须启动两个不同的位置提供商(GPS和网络)并管理每个提供商的生命周期。不仅如此,我还必须在多个活动中复制相同的代码以满足2。过去我曾尝试使用getBestProvider()将解决方案简化为只使用一个位置提供者,但这似乎只会给您提供最好的"理论"提供者,而不是实际上会给您带来最好结果的提供者。

    有没有一个更简单的方法来完成这个?


    我要做的是:

  • 首先,我检查启用了哪些提供程序。一些可能在设备上被禁用,一些可能在应用程序清单中被禁用。
  • 如果任何提供程序可用,我将启动位置侦听器和超时计时器。在我的例子中是20秒,可能不够GPS,所以你可以放大它。
  • 如果从位置侦听器获取更新,则使用提供的值。我停止收听和计时。
  • 如果我没有得到任何更新和计时器,我必须使用最后已知的值。
  • 我从可用的提供程序中获取最新的已知值,并选择其中最新的值。
  • 以下是我如何使用我的课程:

    1
    2
    3
    4
    5
    6
    7
    8
    LocationResult locationResult = new LocationResult(){
        @Override
        public void gotLocation(Location location){
            //Got the location!
        }
    };
    MyLocation myLocation = new MyLocation();
    myLocation.getLocation(this, locationResult);

    这是我的位置分类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    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获得更新,那么您可以使用网络提供的值。

    另一种方法是使用locationclient http://developer.android.com/training/location/retrieve-current.html。但它需要在用户设备上安装Google Play Services APK。


    在寻找了如何获得最佳精确用户位置的最佳实现之后,我设法将所有最佳方法结合起来,并提出了以下类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    /**
     * Retrieve accurate location from GPS or network services.
     *
     *
     * Class usage example:
     *
     * public void onCreate(Bundle savedInstanceState) {
     *      ...
     *      my_location = new MyLocation();
     *      my_location.init(main.this, locationResult);
     * }
     *
     *
     * public LocationResult locationResult = new LocationResult(){
     *      @Override
     *      public void gotLocation(final Location location){
     *          // do something
     *          location.getLongitude();
     *          location.getLatitude();
     *      }
     *  };
     */
    class MyLocation{

        /**
         * If GPS is enabled.
         * Use minimal connected satellites count.
         */
        private static final int min_gps_sat_count = 5;

        /**
         * Iteration step time.
         */
        private static final int iteration_timeout_step = 500;

        LocationResult locationResult;
        private Location bestLocation = null;
        private Handler handler = new Handler();
        private LocationManager myLocationManager;
        public Context context;

        private boolean gps_enabled = false;

        private int counts    = 0;
        private int sat_count = 0;

        private Runnable showTime = new Runnable() {

             public void run() {
                boolean stop = false;
                counts++;
                System.println("counts=" + counts);

                //if timeout (1 min) exceeded, stop tying
                if(counts > 120){
                    stop = true;
                }

                //update last best location
                bestLocation = getLocation(context);

                //if location is not ready or don`t exists, try again
                if(bestLocation == null && gps_enabled){
                    System.println("BestLocation not ready, continue to wait");
                    handler.postDelayed(this, iteration_timeout_step);
                }else{
                    //if best location is known, calculate if we need to continue to look for better location
                    //if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec)  
                    if(stop == false && !needToStop()){
                        System.println("Connected" + sat_count +" sattelites. continue waiting..");
                        handler.postDelayed(this, iteration_timeout_step);
                    }else{
                        System.println("#########################################");
                        System.println("BestLocation finded return result to main. sat_count=" + sat_count);
                        System.println("#########################################");

                        // removing all updates and listeners
                        myLocationManager.removeUpdates(gpsLocationListener);
                        myLocationManager.removeUpdates(networkLocationListener);    
                        myLocationManager.removeGpsStatusListener(gpsStatusListener);
                        sat_count = 0;

                        // send best location to locationResult
                        locationResult.gotLocation(bestLocation);
                    }
                }
             }
        };

        /**
         * Determine if continue to try to find best location
         */
        private Boolean needToStop(){

            if(!gps_enabled){
                              return true;
                         }
              else if(counts <= 4){
                    return false;
                }
                if(sat_count < min_gps_sat_count){
                    //if 20-25 sec and 3 satellites found then stop
                    if(counts >= 40 && sat_count >= 3){
                        return true;
                    }
                    return false;
                }
            }
            return true;
        }

        /**
         * Best location abstract result class
         */
        public static abstract class LocationResult{
             public abstract void gotLocation(Location location);
         }

        /**
         * Initialize starting values and starting best location listeners
         *
         * @param Context ctx
         * @param LocationResult result
         */
        public void init(Context ctx, LocationResult result){
            context = ctx;
            locationResult = result;

            myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

            gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            bestLocation = null;
            counts = 0;

            // turning on location updates
            myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener);
            myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener);
            myLocationManager.addGpsStatusListener(gpsStatusListener);

            // starting best location finder loop
            handler.postDelayed(showTime, iteration_timeout_step);
        }

        /**
         * GpsStatus listener. OnChainged counts connected satellites count.
         */
        public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
            public void onGpsStatusChanged(int event) {

                 if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
                    try {
                        // Check number of satellites in list to determine fix state
                         GpsStatus status = myLocationManager.getGpsStatus(null);
                         Iterable<GpsSatellite>satellites = status.getSatellites();

                         sat_count = 0;

                         Iterator<GpsSatellite>satI = satellites.iterator();
                         while(satI.hasNext()) {
                             GpsSatellite satellite = satI.next();
                             System.println("Satellite: snr=" + satellite.getSnr() +", elevation=" + satellite.getElevation());                        
                             sat_count++;
                         }
                    } catch (Exception e) {
                        e.printStackTrace();
                        sat_count = min_gps_sat_count + 1;
                    }

                     System.println("#### sat_count =" + sat_count);
                 }
             }
        };

        /**
         * Gps location listener.
         */
        public final LocationListener gpsLocationListener = new LocationListener(){
            @Override
             public void onLocationChanged(Location location){

            }
             public void onProviderDisabled(String provider){}
             public void onProviderEnabled(String provider){}
             public void onStatusChanged(String provider, int status, Bundle extras){}
        };

        /**
         * Network location listener.
         */
        public final LocationListener networkLocationListener = new LocationListener(){
            @Override
             public void onLocationChanged(Location location){

            }
             public void onProviderDisabled(String provider){}
             public void onProviderEnabled(String provider){}
             public void onStatusChanged(String provider, int status, Bundle extras){}
        };


        /**
         * Returns best location using LocationManager.getBestProvider()
         *
         * @param context
         * @return Location|null
         */
        public static Location getLocation(Context context){
            System.println("getLocation()");

            // fetch last known location and update it
            try {
                LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_FINE);
                 criteria.setAltitudeRequired(false);
                 criteria.setBearingRequired(false);
                 criteria.setCostAllowed(true);
                 String strLocationProvider = lm.getBestProvider(criteria, true);

                 System.println("strLocationProvider=" + strLocationProvider);
                 Location location = lm.getLastKnownLocation(strLocationProvider);
                 if(location != null){
                    return location;
                 }
                 return null;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    如果启用GPS,该类将尝试连接到min_gps_sat_count卫星。否则返回LocationManager.getBestProvider()位置。检查代码!


    使用Fedor的解决方案,我经历了多次执行回调gotLocation。当gotlocation方法"足够长"时,似乎是由于重写的LocationListener.onLocationChanged方法中的争用条件造成的。我不确定,但我猜removeUpdates可以防止新消息在循环器队列中排队,但它不会删除那些已经排队但尚未消耗的消息。因此,比赛条件。

    为了减少这种错误行为的可能性,可以在触发OnLocationChanged事件之前调用removeUpdates,但我们仍然有争用条件。

    我发现最好的解决办法是用requestSingleUpdate替换requestLocationUpdates

    这是我的版本,基于Fedor的解决方案,使用处理程序向Looper线程发送消息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    public class LocationResolver {
        private Timer timer;
        private LocationManager locationManager;
        private LocationResult locationResult;
        private boolean gpsEnabled = false;
        private boolean networkEnabled = false;
        private Handler locationTimeoutHandler;

        private final Callback locationTimeoutCallback = new Callback() {
            public boolean handleMessage(Message msg) {
                locationTimeoutFunc();
                return true;
            }

            private void locationTimeoutFunc() {  
                locationManager.removeUpdates(locationListenerGps);
                locationManager.removeUpdates(locationListenerNetwork);

                Location networkLocation = null, gpsLocation = null;
                if (gpsEnabled)
                    gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (networkEnabled)
                    networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

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

                if (gpsLocation != null) {
                    locationResult.gotLocation(gpsLocation);
                    return;
                }
                if (networkLocation != null) {
                    locationResult.gotLocation(networkLocation);
                    return;
                }
                locationResult.gotLocation(null);          
            }
        };
        private final LocationListener locationListenerGps = new LocationListener() {
            public void onLocationChanged(Location location) {              
                timer.cancel();
                locationResult.gotLocation(location);
                locationManager.removeUpdates(this);
                locationManager.removeUpdates(locationListenerNetwork);
            }

            public void onProviderDisabled(String provider) {
            }

            public void onProviderEnabled(String provider) {
            }

            public void onStatusChanged(String provider, int status, Bundle extras) {
            }
        };
        private final LocationListener locationListenerNetwork = new LocationListener() {
            public void onLocationChanged(Location location) {    
                timer.cancel();
                locationResult.gotLocation(location);
                locationManager.removeUpdates(this);
                locationManager.removeUpdates(locationListenerGps);
            }

            public void onProviderDisabled(String provider) {
            }

            public void onProviderEnabled(String provider) {
            }

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

        public void prepare() {
            locationTimeoutHandler = new Handler(locationTimeoutCallback);
        }

        public synchronized boolean getLocation(Context context, LocationResult result, int maxMillisToWait) {
            locationResult = result;
            if (locationManager == null)
                locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

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

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

            if (gpsEnabled)
                locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper());
                //locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
            if (networkEnabled)
                locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerNetwork, Looper.myLooper());
                //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);

            timer = new Timer();
            timer.schedule(new GetLastLocationTask(), maxMillisToWait);
            return true;
        }

        private class GetLastLocationTask extends TimerTask {
            @Override
            public void run() {
                locationTimeoutHandler.sendEmptyMessage(0);
            }
        }

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

    我从自定义的looper线程使用这个类,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    public class LocationGetter {
        private final Context context;
        private Location location = null;
        private final Object gotLocationLock = new Object();
        private final LocationResult locationResult = new LocationResult() {            
            @Override
            public void gotLocation(Location location) {
                synchronized (gotLocationLock) {
                    LocationGetter.this.location = location;
                    gotLocationLock.notifyAll();
                    Looper.myLooper().quit();
                }
            }
        };

        public LocationGetter(Context context) {
            if (context == null)
                throw new IllegalArgumentException("context == null");

            this.context = context;
        }

        public synchronized Coordinates getLocation(int maxWaitingTime, int updateTimeout) {
            try {
                final int updateTimeoutPar = updateTimeout;
                synchronized (gotLocationLock) {            
                    new Thread() {
                        public void run() {
                            Looper.prepare();
                            LocationResolver locationResolver = new LocationResolver();
                            locationResolver.prepare();
                            locationResolver.getLocation(context, locationResult, updateTimeoutPar);
                            Looper.loop();
                        }
                    }.start();

                    gotLocationLock.wait(maxWaitingTime);
                }
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            if (location != null)
                coordinates = new Coordinates(location.getLatitude(), location.getLongitude());
            else
                coordinates = Coordinates.UNDEFINED;
            return coordinates;
        }
    }

    其中,坐标是一个简单的类,具有两个属性:纬度和经度。


    我已经创建了一个小应用程序,并逐步描述,以获取当前位置的GPS坐标。

    enter image description here

    完成以下URL中的示例源代码:

    Get Current Location coordinates , City name - in Android

    看看它是如何工作的:

    • 我们只需要在清单文件中添加此权限

      1
      2
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">  
      </uses-permission>
    • 并创建这样的locationManager实例

      1
      2
      LocationManager locationManager = (LocationManager)
                                        getSystemService(Context.LOCATION_SERVICE);
    • 检查GPS是否启用

    • 然后实现locationListener并获取坐标

      1
      2
      3
      LocationListener locationListener = new MyLocationListener();  
      locationManager.requestLocationUpdates(  
      LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
    • 这是要做的示例代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    /*----------Listener class to get coordinates ------------- */
    private class MyLocationListener implements LocationListener {

        @Override
        public void onLocationChanged(Location loc) {
            editLocation.setText("");
            pb.setVisibility(View.INVISIBLE);
            Toast.makeText(
                getBaseContext(),
               "Location changed: Lat:" + loc.getLatitude() +" Lng:"
                    + loc.getLongitude(), Toast.LENGTH_SHORT).show();
            String longitude ="Longitude:" + loc.getLongitude();
            Log.v(TAG, longitude);
            String latitude ="Latitude:" + loc.getLatitude();
            Log.v(TAG, latitude);
            /*-------to get City-Name from coordinates -------- */
            String cityName = null;
            Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
            List<Address> addresses;
            try {
                addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
                if (addresses.size() > 0)
                    System.out.println(addresses.get(0).getLocality());
                cityName = addresses.get(0).getLocality();
            } catch (IOException e) {
                e.printStackTrace();
            }
            String s = longitude +"
    " + latitude +"

    My Current City is:"
                + cityName;
            editLocation.setText(s);
        }

        @Override
        public void onProviderDisabled(String provider) {}

        @Override
        public void onProviderEnabled(String provider) {}

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


    您可以一直使用locationManager.getLastKnownLocation(),但就像它说的那样,它可能已经过时了。

    一个简单的方法来获得一个一般的位置可以注册网络(通常相当快)。

    1
    2
    3
    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(
         LocationManager.NETWORK_PROVIDER, 1000, 1000, this);

    然后做

    1
    locationManager.removeUpdates(this);

    在侦听器的onLocationChanged()方法中。


    我已经在demonuts.com上写了详细的教程,介绍了当前的位置。您可以在这里找到更多的描述,还可以下载整个演示源代码,以便更好地理解。

    已经有很多答案了,但我想展示使用谷歌API获取位置的最新方法,这样新的程序员可以使用新方法:

    首先,把这个放进梯度文件

    1
    compile 'com.google.android.gms:play-services:8.4.0'

    然后实现必要的接口

    1
    public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

    声明实例

    1
    2
    3
    4
      private GoogleApiClient mGoogleApiClient;
      private Location mLocation;
      private LocationManager locationManager;
      private LocationRequest mLocationRequest;

    把这个放在onCreate()

    1
    2
    3
    4
    5
    6
     mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    最后,重写必要的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     @Override
        public void onConnected(Bundle bundle) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            if(mLocation == null){
                startLocationUpdates();
            }
            if (mLocation != null) {
                double latitude = mLocation.getLatitude();
                double longitude = mLocation.getLongitude();
            } else {
                // Toast.makeText(this,"Location not Detected", Toast.LENGTH_SHORT).show();
            }
        }

        protected void startLocationUpdates() {
            // Create the location request
            mLocationRequest = LocationRequest.create()
                    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                    .setInterval(UPDATE_INTERVAL)
                    .setFastestInterval(FASTEST_INTERVAL);
            // Request location updates
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                    mLocationRequest, this);
            Log.d("reque","--->>>>");
        }

        @Override
        public void onConnectionSuspended(int i) {
            Log.i(TAG,"Connection Suspended");
            mGoogleApiClient.connect();
        }

        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Log.i(TAG,"Connection failed. Error:" + connectionResult.getErrorCode());
        }

        @Override
        public void onStart() {
            super.onStart();
            mGoogleApiClient.connect();
        }

        @Override
        public void onStop() {
            super.onStop();
            if (mGoogleApiClient.isConnected()) {
                mGoogleApiClient.disconnect();
            }
        }
        @Override
        public void onLocationChanged(Location location) {

        }

    在运行应用程序之前,不要忘记在设备中启动GPS。


    我不确定基于位置的服务是否可以从GPS以外的其他基础设施获取位置,但根据那篇文章,这似乎是可能的:

    Applications can call on any of
    several types of positioning methods.

    Using the mobile phone network: The
    current cell ID can be used to
    identify the Base Transceiver Station
    (BTS) that the device is communicating
    with and the location of that BTS.
    Clearly, the accuracy of this method
    depends on the size of the cell, and
    can be quite inaccurate. A GSM cell
    may be anywhere from 2 to 20
    kilometers in diameter. Other
    techniques used along with cell ID can
    achieve accuracy within 150 meters.

    Using satellites: The Global
    Positioning System (GPS), controlled
    by the US Department of Defense, uses
    a constellation of 24 satellites
    orbiting the earth. GPS determines the
    device's position by calculating
    differences in the times signals from
    different satellites take to reach the
    receiver. GPS signals are encoded, so
    the mobile device must be equipped
    with a GPS receiver. GPS is
    potentially the most accurate method
    (between 4 and 40 meters if the GPS
    receiver has a clear view of the sky),
    but it has some drawbacks: The extra
    hardware can be costly, consumes
    battery while in use, and requires
    some warm-up after a cold start to get
    an initial fix on visible satellites.
    It also suffers from"canyon effects"
    in cities, where satellite visibility
    is intermittent.

    Using short-range
    positioning beacons: In relatively
    small areas, such as a single
    building, a local area network can
    provide locations along with other
    services. For example, appropriately
    equipped devices can use Bluetooth for
    short-range positioning.


    使用以下代码,它将提供可用的最佳提供商:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    String locCtx = Context.LOCATION_SERVICE;

    LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx);

    Criteria criteria  = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);
    criteria.setCostAllowed(true);
    criteria.setPowerRequirement(Criteria.POWER_LOW);

    String provider = locationMgr.getBestProvider(criteria, true);

    System.out.println("Best Available provider::::"+provider);


    建议使用LocationClient

    首先,定义位置更新间隔值。根据你的需要调整这个。

    1
    2
    3
    4
    private static final int MILLISECONDS_PER_SECOND = 1000;
    private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
    private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
    private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;

    让你的Activity实施GooglePlayServicesClient.ConnectionCallbacksGooglePlayServicesClient.OnConnectionFailedListenerLocationListener

    1
    2
    public class LocationActivity extends Activity implements
    GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {}

    然后,在你的ActivityonCreate()方法中设置一个LocationClient

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mLocationClient = new LocationClient(this, this, this);

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
    }

    向您的Activity中添加所需的方法;onConnected()是在LocationClient连接时调用的方法。onLocationChanged()是您检索最新位置的地方。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.w(TAG,"Location client connection failed");
    }

    @Override
    public void onConnected(Bundle dataBundle) {
        Log.d(TAG,"Location client connected");
        mLocationClient.requestLocationUpdates(mLocationRequest, this);
    }

    @Override
    public void onDisconnected() {
        Log.d(TAG,"Location client disconnected");
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            Log.d(TAG,"Updated Location:" + Double.toString(location.getLatitude()) +"," + Double.toString(location.getLongitude()));
        } else {
            Log.d(TAG,"Updated location NULL");
        }
    }

    一定要连接/断开LocationClient,这样它只在绝对必要时使用额外的电池,这样GPS就不会无限期地运行。为了从中获取数据,必须连接LocationClient

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void onResume() {
        super.onResume();
        mLocationClient.connect();
    }

    public void onStop() {
        if (mLocationClient.isConnected()) {
            mLocationClient.removeLocationUpdates(this);
        }
        mLocationClient.disconnect();
        super.onStop();
    }

    获取用户的位置。首先尝试使用LocationClient;如果失败,返回LocationManager

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public Location getLocation() {
        if (mLocationClient != null && mLocationClient.isConnected()) {
            return mLocationClient.getLastLocation();
        } else {
            LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
            if (locationManager != null) {
                Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (lastKnownLocationGPS != null) {
                    return lastKnownLocationGPS;
                } else {
                    return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                }
            } else {
                return null;
            }
        }
    }


    实际上,我们可以使用这两个提供商(GPS和网络)。他们只是分享一个公共听众:

    1
    2
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener);

    这是必需的,因为总是需要及时调用onLocationChanged()方法。


    这是提供用户当前位置的代码

    创建映射活动:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    public class Maps extends MapActivity {

        public static final String TAG ="MapActivity";
        private MapView mapView;
        private LocationManager locationManager;
        Geocoder geocoder;
        Location location;
        LocationListener locationListener;
        CountDownTimer locationtimer;
        MapController mapController;
        MapOverlay mapOverlay = new MapOverlay();

        @Override
        protected void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            setContentView(R.layout.main);
            initComponents();
            mapView.setBuiltInZoomControls(true);
            mapView.setSatellite(true);
            mapView.setTraffic(true);
            mapView.setStreetView(true);
            mapController = mapView.getController();
            mapController.setZoom(16);
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            if (locationManager == null) {
                Toast.makeText(Maps.this,"Location Manager Not Available",
                    Toast.LENGTH_SHORT).show();
                return;
            }
            location = locationManager
                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (location == null)
                location = locationManager
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            if (location != null) {
                double lat = location.getLatitude();
                double lng = location.getLongitude();
                Toast.makeText(Maps.this,"Location Are" + lat +":" + lng,
                    Toast.LENGTH_SHORT).show();
                GeoPoint point = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
                mapController.animateTo(point, new Message());
                mapOverlay.setPointToDraw(point);
                List<Overlay> listOfOverlays = mapView.getOverlays();
                listOfOverlays.clear();
                listOfOverlays.add(mapOverlay);
            }
            locationListener = new LocationListener() {

                public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}

                public void onProviderEnabled(String arg0) {}

                public void onProviderDisabled(String arg0) {}

                public void onLocationChanged(Location l) {
                    location = l;
                    locationManager.removeUpdates(this);
                    if (l.getLatitude() == 0 || l.getLongitude() == 0) {
                    } else {
                        double lat = l.getLatitude();
                        double lng = l.getLongitude();
                        Toast.makeText(Maps.this,"Location Are" + lat +":" + lng,
                            Toast.LENGTH_SHORT).show();
                    }
                }
            };
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
                locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, 1000, 10f, locationListener);
            locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 1000, 10f, locationListener);
            locationtimer = new CountDownTimer(30000, 5000) {

                @Override
                public void onTick(long millisUntilFinished) {
                    if (location != null) locationtimer.cancel();
                }

                @Override
                public void onFinish() {
                    if (location == null) {
                    }
                }
            };
            locationtimer.start();
        }

        public MapView getMapView() {
            return this.mapView;
        }

        private void initComponents() {
            mapView = (MapView) findViewById(R.id.map_container);
            ImageView ivhome = (ImageView) this.findViewById(R.id.imageView_home);
            ivhome.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    Intent intent = new Intent(Maps.this, GridViewContainer.class);
                    startActivity(intent);
                    finish();
                }
            });
        }

        @Override
        protected boolean isRouteDisplayed() {
            return false;
        }

        class MapOverlay extends Overlay {

            private GeoPoint pointToDraw;

            public void setPointToDraw(GeoPoint point) {
                pointToDraw = point;
            }

            public GeoPoint getPointToDraw() {
                return pointToDraw;
            }

            @Override
            public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
                    long when) {
                super.draw(canvas, mapView, shadow);
                Point screenPts = new Point();
                mapView.getProjection().toPixels(pointToDraw, screenPts);
                Bitmap bmp = BitmapFactory.decodeResource(getResources(),
                    R.drawable.select_map);
                canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 24, null);
                return true;
            }
        }
    }

    MIN .XML:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/black"
            android:orientation="vertical">

            <com.google.android.maps.MapView
                android:id="@+id/map_container"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:apiKey="yor api key"
                android:clickable="true"
                android:focusable="true" />

        </LinearLayout>

    并在清单中定义以下权限:

    1
    2
    3
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    要获取和显示用户的当前位置,您还可以使用MyLocationOverlay。假设您的活动中有一个mapView字段。要显示用户位置,只需执行以下操作:

    1
    2
    3
    myLocationOverlay = new MyLocationOverlay(this, mapView);
    myLocationOverlay.enableMyLocation();
    mapView.getOverlays().add(myLocationOverlay);

    这将从GPS或网络中获取当前位置。如果两者都失败,enableMyLocation()将返回false

    至于该地区周围事物的位置,一个ItemizedOverlay应该能做到这一点。

    希望我没有误解你的问题。祝你好运。


    即使这里已经给出了答案。我只是想把这个分享给全世界,以防遇到这样的情况。

    我的要求是,我需要在最长30到35秒内获得用户的当前位置,所以这里是我根据Nirav Ranpara的答案得出的解决方案。

    1。我做了mylocationmanager.java类,它处理所有的GPS和网络事务。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;

    import com.app.callbacks.OnLocationDetectectionListener;

    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.provider.Settings;
    import android.util.Log;
    import android.widget.Toast;

    public class MyLocationManager {
        /** The minimum distance to GPS change Updates in meters **/
        private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS = 2; // 2
                                                                        // meters
        /** The minimum time between GPS updates in milliseconds **/
        private final long MIN_TIME_BW_UPDATES_OF_GPS = 1000 * 5 * 1; // 5
                                                                        // seconds

        /** The minimum distance to NETWORK change Updates in meters **/
        private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK = 5; // 5
                                                                            // meters
        /** The minimum time between NETWORK updates in milliseconds **/
        private final long MIN_TIME_BW_UPDATES_OF_NETWORK = 1000 * 10 * 1; // 10
                                                                            // seconds

        /**
         * Lets just say i don't trust the first location that the is found. This is
         * to avoid that
         **/

        private int NetworkLocationCount = 0, GPSLocationCount = 0;
        private boolean isGPSEnabled;
        private boolean isNetworkEnabled;
        /**
         * Don't do anything if location is being updated by Network or by GPS
         */
        private boolean isLocationManagerBusy;
        private LocationManager locationManager;
        private Location currentLocation;
        private Context mContext;
        private OnLocationDetectectionListener mListener;

        public MyLocationManager(Context mContext,
                OnLocationDetectectionListener mListener) {
            this.mContext = mContext;
            this.mListener = mListener;
        }

        /**
         * Start the location manager to find my location
         */
        public void startLocating() {
            try {
                locationManager = (LocationManager) mContext
                        .getSystemService(Context.LOCATION_SERVICE);

                // Getting GPS status
                isGPSEnabled = locationManager
                        .isProviderEnabled(LocationManager.GPS_PROVIDER);

                // Getting network status
                isNetworkEnabled = locationManager
                        .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

                if (!isGPSEnabled && !isNetworkEnabled) {
                    // No network provider is enabled
                    showSettingsAlertDialog();
                } else {
                    // If GPS enabled, get latitude/longitude using GPS Services
                    if (isGPSEnabled) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES_OF_GPS,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS,
                                gpsLocationListener);

                    }
                    if (isNetworkEnabled) {
                        locationManager.requestLocationUpdates(
                                LocationManager.NETWORK_PROVIDER,
                                MIN_TIME_BW_UPDATES_OF_NETWORK,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK,
                                networkLocationListener);

                    }
                }
                /**
                 * My 30 seconds plan to get myself a location
                 */
                ScheduledExecutorService se = Executors
                        .newSingleThreadScheduledExecutor();
                se.schedule(new Runnable() {

                    @Override
                    public void run() {
                        if (currentLocation == null) {
                            if (isGPSEnabled) {
                                currentLocation = locationManager
                                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            } else if (isNetworkEnabled) {
                                currentLocation = locationManager
                                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                            }
                            if (currentLocation != null && mListener != null) {
                                locationManager.removeUpdates(gpsLocationListener);
                                locationManager
                                        .removeUpdates(networkLocationListener);
                                mListener.onLocationDetected(currentLocation);
                            }
                        }
                    }
                }, 30, TimeUnit.SECONDS);

            } catch (Exception e) {
                Log.e("Error Fetching Location", e.getMessage());
                Toast.makeText(mContext,
                       "Error Fetching Location" + e.getMessage(),
                        Toast.LENGTH_SHORT).show();
            }
        }

        /**
         * Handle GPS location listener callbacks
         */
        private LocationListener gpsLocationListener = new LocationListener() {

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {

                if (GPSLocationCount != 0 && !isLocationManagerBusy) {
                    Log.d("GPS Enabled","GPS Enabled");
                    isLocationManagerBusy = true;
                    currentLocation = location;
                    locationManager.removeUpdates(gpsLocationListener);
                    locationManager.removeUpdates(networkLocationListener);
                    isLocationManagerBusy = false;
                    if (currentLocation != null && mListener != null) {
                        mListener.onLocationDetected(currentLocation);
                    }
                }
                GPSLocationCount++;
            }
        };
        /**
         * Handle Network location listener callbacks
         */
        private LocationListener networkLocationListener = new LocationListener() {

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {
                if (NetworkLocationCount != 0 && !isLocationManagerBusy) {
                    Log.d("Network","Network");
                    isLocationManagerBusy = true;
                    currentLocation = location;
                    locationManager.removeUpdates(gpsLocationListener);
                    locationManager.removeUpdates(networkLocationListener);
                    isLocationManagerBusy = false;
                    if (currentLocation != null && mListener != null) {
                        mListener.onLocationDetected(currentLocation);
                    }
                }
                NetworkLocationCount++;
            }
        };

        /**
         * Function to show settings alert dialog. On pressing the Settings button
         * it will launch Settings Options.
         * */
        public void showSettingsAlertDialog() {
            AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

            // Setting Dialog Title
            alertDialog.setTitle("GPS is settings");

            // Setting Dialog Message
            alertDialog
                    .setMessage("GPS is not enabled. Do you want to go to settings menu?");

            // On pressing the Settings button.
            alertDialog.setPositiveButton("Settings",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(
                                    Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                            mContext.startActivity(intent);
                        }
                    });

            // On pressing the cancel button
            alertDialog.setNegativeButton("Cancel",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });

            // Showing Alert Message
            alertDialog.show();
        }
    }

    2。我做了一个接口(callback)onlocationDetectionListener.java,以便将结果传达回调用片段或活动

    1
    2
    3
    4
    5
    import android.location.Location;

    public interface OnLocationDetectectionListener {
        public void onLocationDetected(Location mLocation);
    }

    三。然后我做了一个mainAppActivity.java活动来实现OnLocationDetectectionListener接口,下面是我在其中接收位置的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class MainAppActivty extends Activity implements
            OnLocationDetectectionListener {

        private Location currentLocation;
        private MyLocationManager mLocationManager;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            setContentView(R.layout.activity_home);
            super.onCreate(savedInstanceState);
                mLocationManager = new MyLocationManager(this, this);
                mLocationManager.startLocating();
        }

        @Override
        public void onLocationDetected(Location mLocation) {
            //Your new Location is received here
            currentLocation = mLocation;
        }

    4。向清单文件添加以下权限

    1
    2
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    希望这对其他人有帮助:)


    编辑:使用Google Play Services库中最新的位置服务API进行更新(2014年7月)

    我建议您使用新的定位服务API,该API可从Google Play服务库中获得,它提供了一个更强大、更高级的框架,可以自动执行位置提供者选择和电源管理等任务。根据官方文件:"…位置API使您可以轻松地构建位置感知应用程序,而无需关注底层位置技术的细节。它们还允许您通过使用设备硬件的所有功能将功耗降至最低。"

    有关更多信息,请访问:让您的应用程序知道位置

    要查看使用最新位置服务API的完整示例,请访问:android locationclient类已弃用,但在文档中使用


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public static Location getBestLocation(Context ctxt) {
        Location gpslocation = getLocationByProvider(
            LocationManager.GPS_PROVIDER, ctxt);
        Location networkLocation = getLocationByProvider(
            LocationManager.NETWORK_PROVIDER, ctxt);
        Location fetchedlocation = null;
        // if we have only one location available, the choice is easy
        if (gpslocation != null) {
            Log.i("New Location Receiver","GPS Location available.");
            fetchedlocation = gpslocation;
        } else {
            Log.i("New Location Receiver",
               "No GPS Location available. Fetching Network location lat="
                    + networkLocation.getLatitude() +" lon ="
                    + networkLocation.getLongitude());
            fetchedlocation = networkLocation;
        }
        return fetchedlocation;
    }

    /**
     * get the last known location from a specific provider (network/gps)
     */
    private static Location getLocationByProvider(String provider, Context ctxt) {
        Location location = null;
        // if (!isProviderSupported(provider)) {
        // return null;
        // }
        LocationManager locationManager = (LocationManager) ctxt
                .getSystemService(Context.LOCATION_SERVICE);
        try {
            if (locationManager.isProviderEnabled(provider)) {
                location = locationManager.getLastKnownLocation(provider);
            }
        } catch (IllegalArgumentException e) {
            Log.i("New Location Receiver","Cannot access Provider" + provider);
        }
        return location;
    }

    有点晚了,但在这种情况下,我会使用谷歌地图API,并使用谷歌地图的lat和long api标记附近的位置。另外,如果你能在地图上显示他/她的位置,用户体验会更好。无需为更新用户位置或使用Android API进行浏览而烦恼。让谷歌地图为您处理内部问题。

    @Emmby可能已经在他的应用程序中解决了这个问题,但是为了将来的参考,我向其他开发者推荐的是谷歌地图API中的特定位置的东西。

    编辑:用于在谷歌地图中显示用户位置的链接


    在安卓系统中需要很多东西来更新位置,需要大量的玻利erplate代码。

    你需要照顾好

    • Google Play服务可用性检查,
    • 如果google play服务旧或不可用,请更新该服务
    • 对话创建googleapiclient及其回调连接、断开连接等。
    • 停止和释放用于位置更新的资源
    • 处理位置权限方案
    • 检查位置服务是否打开或关闭
    • 获取最新的已知位置也不是那么容易
    • 如果在某段时间后未获取位置,则返回到最后一个已知位置

    我已经创建了android easylocation(小型android库),它将处理所有这些东西,您可以专注于业务逻辑。

    你所需要的只是延长易感活动和这个

    1
    requestSingleLocationFix(easyLocationRequest);

    1
    requestLocationUpdates(easyLocationRequest);

    请访问https://github.com/akhgupta/android-easylocation查看所需的示例应用程序和步骤。


    这是我请求用户权限的方式。

    在androidmanifest.xml中的应用程序标记之外,添加这些权限请求。

    1
    2
    3
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    然后在应用程序渐变文件中添加谷歌的位置依赖项。

    1
    implementation 'com.google.android.gms:play-services-location:15.0.0'

    现在声明一些全局变量。

    1
    2
    3
    4
    private lateinit var mFusedLocationProvider:FusedLocationProviderClient
    private lateinit var mLocationCallback: LocationCallback
    private lateinit var mLocationRequest: LocationRequest
    private var mLocationPermissionGranted:Boolean = false

    在你活动的onCreate方法中(我无法正确地格式化代码,为此道歉)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)

    //Location Callback
    mLocationCallback = object: LocationCallback(){
     override fun onLocationResult(p0: LocationResult?) {
      if(p0==null){
         //todo(request user to enable location from settings then remove return)
         return
      }else{
          getDeviceLocation()
           }
      }
    }

    //Location Request
    mLocationRequest = LocationRequest.create()
    mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
    //Set the Interval for Latest Interval Update
    mLocationRequest.interval = 5000
    //Set How Many Location Updated you Want
    mLocationRequest.numUpdates = 1

    getLocationPermission()
    getDeviceLocation()

    现在创建这两个函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     private fun getLocationPermission() {

                val permission:Array<String> = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION)
                if(ContextCompat.checkSelfPermission(applicationContext,Constant.FINE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
                    if(ContextCompat.checkSelfPermission(applicationContext,Constant.COARSE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
                        mLocationPermissionGranted = true
                    }
                }else{
                    ActivityCompat.requestPermissions(this,permission,Constant.LOCATION_REQUEST_CODE)
                }

        }

    第二方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    private fun getDeviceLocation() {
            try{
                if(mLocationPermissionGranted){

                    mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task<Location> ->
                        if(task.isSuccessful){
                            var currentLocation: Location? = task.result
                            if(currentLocation!=null){

                                Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" +
                                       "${currentLocation.longitude}")
                            }

                            else
                                mFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null)
                        }
                    })
                }
            }catch (e:SecurityException){
                Log.e("Error","Security Exception ${e.message}")
            }
        }

    为康斯坦特KT

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Constant{
        companion object {

            //Location Request Settings
            const val SET_INTERVAL:Long = 2000
            const val NUM_UPDATES:Int = 1

            //Location Permission
            const val FINE_LOCATION:String = android.Manifest.permission.ACCESS_FINE_LOCATION
            const val COARSE_LOCATION:String = android.Manifest.permission.ACCESS_COARSE_LOCATION
        }
    }

    从过去一年多的时间里,我一直在利用GPS提供商和网络提供商的组合来获取当前的位置,它运行良好,但从最近几个月开始,经过长时间的延迟,我得到了位置,所以我切换到最新的API FusedLocationProviderClient,它运行良好。

    这是我使用fusedLocationProviderClient编写的用于获取当前位置的类。在下面的代码中,我用了一个定时器来等一下,得到了当前的位置,我安排了定时器15秒的延时,你可以根据自己来改变它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    private static FusedLocationService ourInstance;
    private final LocationRequest locationRequest;
    private FusedLocationProviderClient mFusedLocationClient;
    private Location mLastLocation;
    private Context context;
    private FindOutLocation findOutLocation;
    private boolean callbackTriggered = false;
    private Timer timer;

    public static FusedLocationService getInstance(Context pContext) {

        if (null == ourInstance) ourInstance = new FusedLocationService(pContext);

        return ourInstance;
    }

    private FusedLocationService(Context pContext) {
        context = pContext;
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
        locationRequest = getLocationRequest();
        requestLocation(context);
    }

    public Location getLastKnownLocation() {
        return mLastLocation;
    }

    private void requestLocation(Context context) {

        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null);
        mFusedLocationClient.getLastLocation().addOnSuccessListener(location -> {
            if (location != null) {
                mLastLocation = location;
                triggerCallback(mLastLocation);
            }
        });
    }

    private LocationRequest getLocationRequest() {
        LocationRequest locationRequest = new LocationRequest();
        long INTERVAL = 10 * 1000;
        long FASTEST_INTERVAL = 5 * 1000;
        locationRequest.setInterval(INTERVAL);
        locationRequest.setFastestInterval(FASTEST_INTERVAL);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        return locationRequest;
    }

    private LocationCallback mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            for (Location location : locationResult.getLocations()) {
                if (location != null) mLastLocation = location;
            }
            if (null != mLastLocation) triggerCallback(mLastLocation);
        }
    };

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

    @SuppressLint("MissingPermission")
    public void findLocation(FindOutLocation findOutLocation) {
        long TIMER_TIME_OUT = 15 * 1000;
        this.findOutLocation = findOutLocation;
        callbackTriggered = false;

        try {
            requestLocation(context);
            timer = new Timer();
            timer.schedule(new GetLastLocation(context), TIMER_TIME_OUT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class GetLastLocation extends TimerTask {
        Context context;

        GetLastLocation(Context context) {
            this.context = context;
        }

        @Override
        public void run() {
            triggerCallback(mLastLocation);
        }
    }

    private void triggerCallback(Location location) {
        if (null != location) mLastLocation = location;
        if (!callbackTriggered && null != findOutLocation) {
            callbackTriggered = true;
            removeLocationUpdates();
            findOutLocation.gotLocation(location);
            findOutLocation = null;
        }
    }

    private void removeLocationUpdates() {
        if (null != timer) timer.cancel();
        if (null != mFusedLocationClient)
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
    }
    }

    从活动中调用这个,这是代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
        FusedLocationService.FindOutLocation findOutLocation = new FusedLocationService.FindOutLocation() {
            @Override
            public void gotLocation(Location currentLocation) {
                if (currentLocation != null) {
                    /*TODO DO SOMETHING WITH CURRENT LOCATION*/
                }
            }
        };
        FusedLocationService.getInstance(this).findLocation(findOutLocation);

    在androidmanifest.xml中添加以下条目

    1
    2
    3
    4
    5
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
    <uses-feature android:name="android.hardware.location.gps" />


    简单和最佳的地理定位方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    LocationManager lm = null;
    boolean network_enabled;


    if (lm == null)
                    lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);

                network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

                dialog = ProgressDialog.show(Kikit.this,"","Fetching location...", true);


                final Handler handler = new Handler();
                timer = new Timer();
                TimerTask doAsynchronousTask = new TimerTask() {

                    @Override
                    public void run() {
                        handler.post(new Runnable() {

                            @Override
                            public void run()
                            {

                                Log.e("counter value","value"+counter);

                                if(counter<=8)
                                {
                                    try
                                    {
                                        counter++;


                                        if (network_enabled) {

                                            lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);

                                            Log.e("in network_enabled..","in network_enabled");

                                            // Define a listener that responds to location updates
                                            LocationListener locationListener = new LocationListener()
                                            {


                                                public void onLocationChanged(Location location)
                                                {
                                                    if(attempt == false)

                                                    {
                                                        attempt = true;
                                                        Log.e("in location listener..","in location listener..");
                                                        longi = location.getLongitude();
                                                        lati = location.getLatitude();
                                                        Data.longi ="" + longi;
                                                        Data.lati ="" + lati;


                                                        Log.e("longitude :",""+longi);
                                                        Log.e("latitude :",""+lati);



                                                        if(faceboo_name.equals(""))
                                                        {
                                                            if(dialog!=null){
                                                            dialog.cancel();}
                                                            timer.cancel();
                                                            timer.purge();
                                                            Data.homepage_resume = true;
                                                            lm = null;
                                                            Intent intent = new Intent();                              
                                                            intent.setClass(Kikit.this,MainActivity.class);

                                                            startActivity(intent);      
                                                            finish();
                                                        }
                                                        else
                                                        {          

                                                            isInternetPresent = cd.isConnectingToInternet();

                                                            if (isInternetPresent)
                                                            {
                                                                if(dialog!=null)
                                                                    dialog.cancel();

                                                                Showdata();
                                                            }
                                                            else
                                                            {
                                                                error_view.setText(Data.internet_error_msg);
                                                                error_view.setVisibility(0);
                                                                error_gone();
                                                            }

                                                        }  
                                                    }

                                                }

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

                                                public void onProviderEnabled(String provider) {
                                                    //Toast.makeText(getApplicationContext(),"Location enabled", Toast.LENGTH_LONG).show();

                                                }

                                                public void onProviderDisabled(String provider) {


                                                }
                                            };



                                            // Register the listener with the Location Manager to receive
                                            // location updates
                                            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100000, 10,locationListener);

                                        } else{
                                            //Toast.makeText(getApplicationContext(),"No Internet Connection.", 2000).show();
                                            buildAlertMessageNoGps();

                                        }



                                    } catch (Exception e) {
                                        // TODO
                                        // Auto-generated
                                        // catch
                                        // block
                                    }
                                }
                                else
                                {

                                    timer.purge();
                                    timer.cancel();

                                    if(attempt == false)
                                    {
                                        attempt = true;

                                        String locationProvider = LocationManager.NETWORK_PROVIDER;
                                        // Or use LocationManager.GPS_PROVIDER

                                        try {
                                            Location lastKnownLocation = lm.getLastKnownLocation(locationProvider);

                                            longi = lastKnownLocation.getLongitude();
                                            lati = lastKnownLocation.getLatitude();
                                            Data.longi ="" + longi;
                                            Data.lati ="" + lati;
                                        } catch (Exception e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                            Log.i("exception in loc fetch", e.toString());
                                        }

                                        Log.e("longitude of last known location :",""+longi);
                                        Log.e("latitude of last known location :",""+lati);

                                        if(Data.fb_access_token =="")
                                        {

                                            if(dialog!=null){
                                                dialog.cancel();}
                                            timer.cancel();
                                            timer.purge();
                                            Data.homepage_resume = true;
                                            Intent intent = new Intent();                              
                                            intent.setClass(Kikit.this,MainActivity.class);

                                            startActivity(intent);  
                                            finish();
                                        }
                                        else
                                        {          

                                            isInternetPresent = cd.isConnectingToInternet();

                                            if (isInternetPresent)
                                            {
                                                if(dialog!=null){
                                                    dialog.cancel();}          
                                                Showdata();
                                            }
                                            else
                                            {
                                                error_view.setText(Data.internet_error_msg);
                                                error_view.setVisibility(0);
                                                error_gone();
                                            }

                                        }  

                                    }
                                }
                            }
                        });
                    }
                };
                timer.schedule(doAsynchronousTask, 0, 2000);


    private void buildAlertMessageNoGps() {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);

            builder.setMessage("Your WiFi & mobile network location is disabled , do you want to enable it?")
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {


                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id)
                {
                    startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                    setting_page = true;
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                    dialog.cancel();
                    finish();
                }
            });
            final AlertDialog alert = builder.create();
            alert.show();
        }

    @fedor greate答案的Kotlin版本:

    类的用法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    val locationResult = object : MyLocation.LocationResult() {

        override fun gotLocation(location: Location?) {

            val lat = location!!.latitude
            val lon = location.longitude

            Toast.makeText(context,"$lat --SLocRes-- $lon", Toast.LENGTH_SHORT).show()
        }

    }

    val myLocation = MyLocation()
    myLocation.getLocation(inflater.context, locationResult)

    MyLocation类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    class MyLocation {
        internal lateinit var timer1: Timer
        internal var lm: LocationManager? = null
        internal lateinit var locationResult: LocationResult
        internal var gps_enabled = false
        internal var network_enabled = false

        internal var locationListenerGps: LocationListener = object : LocationListener {


            override fun onLocationChanged(location: Location) {
                timer1.cancel()
                locationResult.gotLocation(location)
                lm!!.removeUpdates(this)
                lm!!.removeUpdates(locationListenerNetwork)
            }

            override fun onProviderDisabled(provider: String) {}
            override fun onProviderEnabled(provider: String) {}
            override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
        }

        internal var locationListenerNetwork: LocationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                timer1.cancel()
                locationResult.gotLocation(location)
                lm!!.removeUpdates(this)
                lm!!.removeUpdates(locationListenerGps)
            }

            override fun onProviderDisabled(provider: String) {}
            override fun onProviderEnabled(provider: String) {}
            override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
        }

        fun getLocation(context: Context, result: LocationResult): Boolean {
            //I use LocationResult callback class to pass location value from MyLocation to user code.
            locationResult = result
            if (lm == null)
                lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?

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

            try {
                network_enabled = lm!!.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
            } catch (ex: Exception) {
            }

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

            if (ActivityCompat.checkSelfPermission(context,
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) run {

                ActivityCompat.requestPermissions(context as Activity,
                    arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 111)
            }


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

        internal inner class GetLastLocation(var context: Context) : TimerTask() {
            override fun run() {
                lm!!.removeUpdates(locationListenerGps)
                lm!!.removeUpdates(locationListenerNetwork)

                var net_loc: Location? = null
                var gps_loc: Location? = null

                if (ActivityCompat.checkSelfPermission(context,
                        Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                ) run {

                    ActivityCompat.requestPermissions(context as Activity,
                        arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION),111)
                }


                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)
            }
        }

         abstract class LocationResult {
              abstract fun gotLocation(location: Location?)
        }
    }

    通过使用FusedLocationProviderAPI,这是最新的API,也是在Android中获得位置的最佳可能性之一。将此添加到build.gradle文件中

    1
    2
    3
    dependencies {
        compile 'com.google.android.gms:play-services:6.5.87'
    }

    您可以通过此URL获取完整的源代码http://javapapers.com/android/android-location-fused-provider/


    我要做的是:

  • 首先,我检查网络或GPS提供商是否启用。一些可能在设备上被禁用,一些可能在应用程序清单中被禁用。如果启用了任何提供程序,我将获取此提供程序的缓存的最后一个位置,并启动此提供程序的位置更新侦听器。
  • 有一种方法可以确定一个位置是否比链接中提到的上次接收的位置更好:-https://developer.android.com/guide/topics/location/strategies.html bestestimate
  • 如果我从位置侦听器获取更新,我会检查此位置是否比以前接收到的位置更好。如果它比将这个位置替换到以前的最佳位置更好(mFinalLocation)。
  • 还有一个处理程序(计时器)持续两分钟,最终停止服务,在onDestroy()服务方法中,停止监听每个提供程序的位置更新。
  • 下面是服务代码。您可以根据需要的位置更新频率来运行它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.support.annotation.Nullable;
    import android.util.Log;


    public class RecordLocationService extends Service {

        private final String TAG = RecordLocationService.class.getSimpleName();

        private final int TWO_MINUTES = 1000 * 60 * 2;

        private LocationManager mLocationManager;

        private MyLocationListener mLocationListeners[] = new MyLocationListener[]{
                new MyLocationListener(LocationManager.NETWORK_PROVIDER),
                new MyLocationListener(LocationManager.GPS_PROVIDER)
        };

        private Location mFinalLocation;

        private class MyLocationListener implements LocationListener {
            private String mProvider;

            public MyLocationListener(String provider) {
                Log.d(TAG,"LocationListener :" + provider);
                mProvider = provider;
            }

            public String getProvider() {
                return mProvider;
            }

            @Override
            public void onLocationChanged(Location location) {
                Log.d(TAG,"onLocationChanged :" + location);

                if (isBetterLocation(location, mFinalLocation)) {
                    Log.d(TAG,"Setting current Final Location to recent most Location for Provider :" + location.getProvider());
                    Log.d(TAG,"Setting current Final Location to :" + location);
                    mFinalLocation = location;
                } else {
                    Log.d(TAG,"Keeping current Final Location to previous Final Location");
                }

            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                Log.d(TAG,"onStatusChanged provider" + provider);
            }

            @Override
            public void onProviderEnabled(String provider) {
                Log.d(TAG,"onProviderEnabled provider" + provider);
            }

            @Override
            public void onProviderDisabled(String provider) {
                Log.d(TAG,"onProviderDisabled provider" + provider);
            }
        }

        private Handler mStopServiceHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1: {
                        stopSelf();
                    }
                    break;
                }
            }
        };

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

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            super.onStartCommand(intent, flags, startId);
            Log.d(TAG,"onStartCommand");
            return START_STICKY;
        }

        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG,"onCreate");
            requestLocation();
            mStopServiceHandler.sendEmptyMessageDelayed(1, TWO_MINUTES);
        }

        private void requestLocation() {
            // Acquire a reference to the system Location Manager
            if (mLocationManager == null) {
                mLocationManager = (LocationManager) this.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
            }

            try {
                if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                    Log.d(TAG,"Fetching Cached Location for Provider :" + LocationManager.NETWORK_PROVIDER);
                    Location cachedNetworkLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                    if (cachedNetworkLocation != null) {
                        Log.d(TAG,"Setting Final Location to Cached Location for Provider :" + LocationManager.NETWORK_PROVIDER);
                        Log.d(TAG,"Setting Final Location to :" + cachedNetworkLocation);
                        mFinalLocation = cachedNetworkLocation;
                    } else {
                        Log.d(TAG,"Cached Location for Provider :" + LocationManager.NETWORK_PROVIDER +" is NULL");
                    }

                    Log.d(TAG,"Requesting Location Update for Provider :" + LocationManager.NETWORK_PROVIDER);
                    mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListeners[0]);
                }

            } catch (SecurityException se) {
                Log.e(TAG, se.getMessage(), se);
            } catch (IllegalArgumentException iae) {
                Log.e(TAG, iae.getMessage(), iae);
            }

            try {
                if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    Log.d(TAG,"Fetching Cached Location for Provider :" + LocationManager.GPS_PROVIDER);
                    Location cachedGPSLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

                    if (cachedGPSLocation != null) {
                        if (isBetterLocation(cachedGPSLocation, mFinalLocation)) {
                            Log.d(TAG,"Setting Final Location to Cached Location for Provider :" + LocationManager.GPS_PROVIDER);
                            Log.d(TAG,"Setting Final Location to :" + cachedGPSLocation);
                            mFinalLocation = cachedGPSLocation;
                        }
                    } else {
                        Log.d(TAG,"Cached Location for Provider :" + LocationManager.GPS_PROVIDER +" is NULL");
                    }

                    Log.d(TAG,"Requesting Location Update for Provider :" + LocationManager.GPS_PROVIDER);
                    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListeners[1]);
                }

            } catch (SecurityException se) {
                Log.e(TAG, se.getMessage(), se);
            } catch (IllegalArgumentException iae) {
                Log.e(TAG, iae.getMessage(), iae);
            }


        }

        /**
         * Determines whether one Location reading is better than the current Location fix
         *
         * @param location            The new Location that you want to evaluate
         * @param currentBestLocation The current Location fix, to which you want to compare the new one
         */
        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());

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

        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestroy");
            if (mLocationManager != null) {
                for (int i = 0; i < mLocationListeners.length; i++) {
                    try {
                        Log.d(TAG,"Removing Location Update for Provider :" + mLocationListeners[i].getProvider());
                        mLocationManager.removeUpdates(mLocationListeners[i]);
                    } catch (Exception ex) {
                        Log.e(TAG,"fail to remove location listeners, ignore", ex);
                    }
                }
            }
        }
    }

    最近重构得到了代码的位置,学习了一些好的思想,最终实现了一个相对完善的库和演示。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    //request all valid provider(network/gps)
    private boolean requestAllProviderUpdates() {
        checkRuntimeEnvironment();
        checkPermission();

        if (isRequesting) {
            EasyLog.d("Request location update is busy");
            return false;
        }


        long minTime = getCheckTimeInterval();
        float minDistance = getCheckMinDistance();

        if (mMapLocationListeners == null) {
            mMapLocationListeners = new HashMap<>();
        }

        mValidProviders = getValidProviders();
        if (mValidProviders == null || mValidProviders.isEmpty()) {
            throw new IllegalArgumentException("Not available provider.");
        }

        for (String provider : mValidProviders) {
            LocationListener locationListener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    if (location == null) {
                        EasyLog.e("LocationListener callback location is null.");
                        return;
                    }
                    printf(location);
                    mLastProviderTimestamp = location.getTime();

                    if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
                        finishResult(location);
                    } else {
                        doLocationResult(location);
                    }

                    removeProvider(location.getProvider());
                    if (isEmptyValidProviders()) {
                        requestTimeoutMsgInit();
                        removeUpdates();
                    }
                }

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

                @Override
                public void onProviderEnabled(String provider) {
                }

                @Override
                public void onProviderDisabled(String provider) {
                }
            };
            getLocationManager().requestLocationUpdates(provider, minTime, minDistance, locationListener);
            mMapLocationListeners.put(provider, locationListener);
            EasyLog.d("Location request %s provider update.", provider);
        }
        isRequesting = true;
        return true;
    }

    //remove request update
    public void removeUpdates() {
        checkRuntimeEnvironment();

        LocationManager locationManager = getLocationManager();
        if (mMapLocationListeners != null) {
            Set<String> keys = mMapLocationListeners.keySet();
            for (String key : keys) {
                LocationListener locationListener = mMapLocationListeners.get(key);
                if (locationListener != null) {
                    locationManager.removeUpdates(locationListener);
                    EasyLog.d("Remove location update, provider is" + key);
                }
            }
            mMapLocationListeners.clear();
            isRequesting = false;
        }
    }

    //Compared with the last successful position, to determine whether you need to filter
    private boolean isNeedFilter(Location location) {
        checkLocation(location);

        if (mLastLocation != null) {
            float distance = location.distanceTo(mLastLocation);
            if (distance < getCheckMinDistance()) {
                return true;
            }
            if (location.getAccuracy() >= mLastLocation.getAccuracy()
                    && distance < location.getAccuracy()) {
                return true;
            }
            if (location.getTime() <= mLastProviderTimestamp) {
                return true;
            }
        }
        return false;
    }

    private void doLocationResult(Location location) {
        checkLocation(location);

        if (isNeedFilter(location)) {
            EasyLog.d("location need to filtered out, timestamp is" + location.getTime());
            finishResult(mLastLocation);
        } else {
            finishResult(location);
        }
    }

    //Return to the finished position
    private void finishResult(Location location) {
        checkLocation(location);

        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        float accuracy = location.getAccuracy();
        long time = location.getTime();
        String provider = location.getProvider();

        if (mLocationResultListeners != null && !mLocationResultListeners.isEmpty()) {
            String format ="Location result:<%f, %f> Accuracy:%f Time:%d Provider:%s";
            EasyLog.i(String.format(format, latitude, longitude, accuracy, time, provider));

            mLastLocation = location;
            synchronized (this) {
                Iterator<LocationResultListener> iterator =  mLocationResultListeners.iterator();
                while (iterator.hasNext()) {
                    LocationResultListener listener = iterator.next();
                    if (listener != null) {
                        listener.onResult(location);
                    }
                    iterator.remove();
                }
            }
        }
    }

    完整代码:https://github.com/bingerz/fastlocation/blob/master/fastlocationlib/src/main/java/cn/bingerz/fastlocation/fastlocation.java

    *每个请求完成的位置,最好删除更新,否则手机状态栏将始终显示定位图标。


    在看到所有答案和问题之后(最简单和强大)。我只被点击了图书馆Android的反应位置。

    当我做了一个位置跟踪应用程序。然后我意识到用电池优化位置跟踪是非常典型的。

    所以我想告诉那些不想在未来优化的情况下维护他们的位置代码的开发人员。使用此库。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ReactiveLocationProvider locationProvider = new

        ReactiveLocationProvider(context);
        locationProvider.getLastKnownLocation()
            .subscribe(new Consumer<Location>() {
                @Override
                public void call(Location location) {
                    doSthImportantWithObtainedLocation(location);
                }
            });

    要放入应用程序级build.gradle的依赖项

    1
    2
    3
    4
    5
    6
    7
    dependencies {
        ...
        compile 'pl.charmas.android:android-reactive-location2:2.1@aar'
        compile 'com.google.android.gms:play-services-location:11.0.4' //you can use newer GMS version if you need
        compile 'com.google.android.gms:play-services-places:11.0.4'
        compile 'io.reactivex:rxjava:2.0.5' //you can override RxJava version if you need
    }

    使用此库的专业人员:

    • 此lib是并将被积极维护的。
    • 你不用担心电池优化。因为开发人员已经尽力了。
    • 安装简单,放置依赖和播放。
    • 轻松连接到播放服务API
    • 获取最后一个已知位置
    • 订阅位置更新使用
    • 位置设置API
    • 管理地理围栏
    • 地址列表的地理代码位置
    • 活动识别
    • 使用当前位置API获取位置
    • 自动完成建议

    在我回答之前,我只想直面我与Neura有关联的事实。现在回答你的问题。因此,您可以使用我们的SDK,而不是浪费时间在编码上以获取用户的位置。集成不到30分钟。Neura为您提供了用户的位置/活动,您可以相应地配置应用程序,以便在收到数据后执行某些任务。以下是使用Neura超过其他活动识别API的几个原因:

  • 不需要编写大量的代码来理解您的用户。
  • 给你准确的结果。
  • 耗电量不到电池的1%。