如何在Android中以编程方式获取当前GPS位置?

我需要以编程方式使用GPS获取我的当前位置。 我该怎么做呢?

1042573 次浏览

我创建了一个带有分步描述的小应用程序来获取当前位置的GPS坐标。

完整的示例源代码在获取当前位置坐标,城市名称-在Android中中。


看看它是如何工作的:

  • 我们需要做的就是在清单文件中添加此权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
  • And create a LocationManager instance like this:

    LocationManager locationManager = (LocationManager)
    getSystemService(Context.LOCATION_SERVICE);
    
  • Check if GPS is enabled or not.

  • And then implement LocationListener and get coordinates:

    LocationListener locationListener = new MyLocationListener();
    locationManager.requestLocationUpdates(
    LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
    
  • Here is the sample code to do so


/*---------- 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 + "\n" + latitude + "\n\nMy 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) {}
}

以下是其他答案的附加信息。

由于Android已经

GPS_PROVIDER and NETWORK_PROVIDER

你可以同时注册并从两个onLocationChanged(Location location)开始获取事件。到目前为止一切顺利。现在的问题是我们需要两个结果还是我们应该采取最好的结果。据我所知GPS_PROVIDER结果比NETWORK_PROVIDER具有更好的准确性。

让我们定义Location字段:

private Location currentBestLocation = null;

在我们开始监听位置更改之前,我们将实现以下方法。此方法返回GPS和网络之间的最后一个已知位置。对于这种方法,更新是最好的。

/**
* @return the last know best location
*/
private Location getLastBestLocation() {
Location locationGPS = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location locationNet = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);


long GPSLocationTime = 0;
if (null != locationGPS) { GPSLocationTime = locationGPS.getTime(); }


long NetLocationTime = 0;


if (null != locationNet) {
NetLocationTime = locationNet.getTime();
}


if ( 0 < GPSLocationTime - NetLocationTime ) {
return locationGPS;
}
else {
return locationNet;
}
}

每次我们检索一个新位置时,我们都会将其与之前的结果进行比较。

...
static final int TWO_MINUTES = 1000 * 60 * 2;
...

我在onLocationChanged中添加了一个新方法:

@Override
public void onLocationChanged(Location location) {


makeUseOfNewLocation(location);


if(currentBestLocation == null){
currentBestLocation = location;
}


....
}




/**
* This method modify the last know good location according to the arguments.
*
* @param location The possible new location.
*/
void makeUseOfNewLocation(Location location) {
if ( isBetterLocation(location, currentBestLocation) ) {
currentBestLocation = location;
}
}


....


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


....

您可以通过GPS_PROVIDER or NETWORK_PROVIDER找到该位置。

Android中的位置服务概述。

这是一个尝试使用GPS查找位置的示例。如果您的GPS不可用,请尝试使用网络查找位置。

GPSTracker.java

 public class GPSTracker extends Service implements LocationListener {


private final Context mContext;


// Flag for GPS status
boolean isGPSEnabled = false;


// Flag for network status
boolean isNetworkEnabled = false;


// Flag for GPS status
boolean canGetLocation = false;


Location location; // Location
double latitude; // Latitude
double longitude; // Longitude


// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters


// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute


// Declaring a Location Manager
protected LocationManager locationManager;


public GPSTracker(Context context) {
this.mContext = context;
getLocation();
}


public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(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
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// If GPS enabled, get latitude/longitude using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}


return location;
}




/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app.
* */
public void stopUsingGPS(){
if(locationManager != null){
locationManager.removeUpdates(GPSTracker.this);
}
}




/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}


// return latitude
return latitude;
}




/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}


// return longitude
return longitude;
}


/**
* Function to check GPS/Wi-Fi enabled
* @return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}




/**
* Function to show settings alert dialog.
* On pressing the Settings button it will launch Settings Options.
* */
public void showSettingsAlert(){
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() {
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() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});


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




@Override
public void onLocationChanged(Location location) {
}




@Override
public void onProviderDisabled(String provider) {
}




@Override
public void onProviderEnabled(String provider) {
}




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




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

活动-AndroidGPSTrackingActivity.java

    public class AndroidGPSTrackingActivity extends Activity {


Button btnShowLocation;


// GPSTracker class
GPSTracker gps;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);


btnShowLocation = (Button) findViewById(R.id.btnShowLocation);


// Show location button click event
btnShowLocation.setOnClickListener(new View.OnClickListener() {


@Override
public void onClick(View arg0) {
// Create class object
gps = new GPSTracker(AndroidGPSTrackingActivity.this);


// Check if GPS enabled
if(gps.canGetLocation()) {


double latitude = gps.getLatitude();
double longitude = gps.getLongitude();


// \n is for new line
Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
} else {
// Can't get location.
// GPS or network is not enabled.
// Ask user to enable GPS/network in settings.
gps.showSettingsAlert();
}
}
});
}
}

布局-main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >


<Button android:id="@+id/btnShowLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Location"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
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 the 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(), 5000);
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);
}
}

我希望这能帮助你…

如果您正在为Android创建新的定位项目,您应该使用新的googleplay定位服务。它更准确,使用起来更简单。

我一直在工作一个开源的GPS跟踪器项目,GpsTracker,几年了。我最近更新了它,以处理来自Android、iOS、Windows Phone和Java我手机的定期更新。它功能齐全,可以满足您的需求,并具有MIT许可证

GpsTracker中的Android项目使用新的Google Play服务,还有两个服务器堆栈(ASP.NETphp)允许您跟踪这些手机。

现在Google Play位置服务已经出现,我建议开发人员开始使用新的融合位置提供程序。你会发现它更容易使用,更准确。请观看创建新的Google Play位置服务API的两个人的谷歌I/O视频超越蓝点:Android位置的新功能

我一直在许多移动平台上使用位置API,我认为这两个人所做的事情真的是革命性的。它摆脱了使用各种提供商的大量复杂性。Stack Overflow充斥着关于使用哪个提供商、是否使用最后已知位置、如何在LocationManager上设置其他属性等问题。他们构建的这个新API消除了大部分不确定性,并使位置服务变得易于使用。

我编写了一个Android应用程序,该应用程序定期使用Google Play位置服务获取位置,并将位置发送到网络服务器,在那里它存储在数据库中,可以在谷歌地图上查看。我编写了客户端软件(适用于Android、iOS、Windows Phone和Java我)和服务器软件(适用于ASP.NET和SQL服务器phpmysql)。该软件在每个平台上以母语编写,并在每个平台的后台正常工作。最后,该软件有MIT许可证。你可以在这里找到Android客户端:

https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android

由于我不喜欢其他答案中的某些代码,因此这是我的简单解决方案。此解决方案旨在在活动或服务中可用来跟踪位置。它确保它永远不会返回过期的数据,除非您显式请求过期数据。它可以在回调模式下运行以在我们收到更新时获取更新,也可以在轮询模式下运行以轮询最新信息。

通用LocationTracker接口。允许我们拥有多种类型的位置跟踪器并轻松插入适当的位置跟踪器:

package com.gabesechan.android.reusable.location;


import android.location.Location;


public interface LocationTracker {
public interface LocationUpdateListener{
public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime);
}


public void start();
public void start(LocationUpdateListener update);


public void stop();


public boolean hasLocation();


public boolean hasPossiblyStaleLocation();


public Location getLocation();


public Location getPossiblyStaleLocation();


}

ProviderLocationTracker-这个类将跟踪GPS或网络的位置。

package com.gabesechan.android.reusable.location;


import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;


public class ProviderLocationTracker implements LocationListener, LocationTracker {


// The minimum distance to change Updates in meters
private static final long MIN_UPDATE_DISTANCE = 10;


// The minimum time between updates in milliseconds
private static final long MIN_UPDATE_TIME = 1000 * 60;


private LocationManager lm;


public enum ProviderType{
NETWORK,
GPS
};
private String provider;


private Location lastLocation;
private long lastTime;


private boolean isRunning;


private LocationUpdateListener listener;


public ProviderLocationTracker(Context context, ProviderType type) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
if(type == ProviderType.NETWORK){
provider = LocationManager.NETWORK_PROVIDER;
}
else{
provider = LocationManager.GPS_PROVIDER;
}
}


public void start(){
if(isRunning){
//Already running, do nothing
return;
}


//The provider is on, so start getting updates.  Update current location
isRunning = true;
lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
lastLocation = null;
lastTime = 0;
return;
}


public void start(LocationUpdateListener update) {
start();
listener = update;


}




public void stop(){
if(isRunning){
lm.removeUpdates(this);
isRunning = false;
listener = null;
}
}


public boolean hasLocation(){
if(lastLocation == null){
return false;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return false; //stale
}
return true;
}


public boolean hasPossiblyStaleLocation(){
if(lastLocation != null){
return true;
}
return lm.getLastKnownLocation(provider)!= null;
}


public Location getLocation(){
if(lastLocation == null){
return null;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return null; //stale
}
return lastLocation;
}


public Location getPossiblyStaleLocation(){
if(lastLocation != null){
return lastLocation;
}
return lm.getLastKnownLocation(provider);
}


public void onLocationChanged(Location newLoc) {
long now = System.currentTimeMillis();
if(listener != null){
listener.onUpdate(lastLocation, lastTime, newLoc, now);
}
lastLocation = newLoc;
lastTime = now;
}


public void onProviderDisabled(String arg0) {


}


public void onProviderEnabled(String arg0) {


}


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

这是FallbackLocationTracker,它将通过GPS和网络跟踪,并使用任何更准确的位置。

package com.gabesechan.android.reusable.location;


import android.content.Context;
import android.location.Location;
import android.location.LocationManager;


public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {




private boolean isRunning;


private ProviderLocationTracker gps;
private ProviderLocationTracker net;


private LocationUpdateListener listener;


Location lastLoc;
long lastTime;


public FallbackLocationTracker(Context context) {
gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
}


public void start(){
if(isRunning){
//Already running, do nothing
return;
}


//Start both
gps.start(this);
net.start(this);
isRunning = true;
}


public void start(LocationUpdateListener update) {
start();
listener = update;
}




public void stop(){
if(isRunning){
gps.stop();
net.stop();
isRunning = false;
listener = null;
}
}


public boolean hasLocation(){
//If either has a location, use it
return gps.hasLocation() || net.hasLocation();
}


public boolean hasPossiblyStaleLocation(){
//If either has a location, use it
return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
}


public Location getLocation(){
Location ret = gps.getLocation();
if(ret == null){
ret = net.getLocation();
}
return ret;
}


public Location getPossiblyStaleLocation(){
Location ret = gps.getPossiblyStaleLocation();
if(ret == null){
ret = net.getPossiblyStaleLocation();
}
return ret;
}


public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
boolean update = false;


//We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
if(lastLoc == null){
update = true;
}
else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
update = true;
}
else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
update = true;
}
else if (newTime - lastTime > 5 * 60 * 1000){
update = true;
}


if(update){
if(listener != null){
listener.onUpdate(lastLoc, lastTime, newLoc, newTime);
}
lastLoc = newLoc;
lastTime = newTime;
}


}
}

由于两者都实现了LocationTracker接口,您可以轻松改变使用哪一个的想法。要在轮询模式下运行类,只需调用start()。要在更新模式下运行它,请调用start(Listener)。

也看看编码上我的博客文章

对于位置检查,您可以使用以下代码。如果返回为false,您可以将其放在主活动的onStart()中并显示警报对话框。

private boolean isLocationAccurate()
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
{
String provider = Settings.Secure
.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if (provider != null && !provider.contains("gps"))
{
return false;
}
}
else
{
try
{
int status = Settings.Secure
.getInt(this.getContentResolver(), Settings.Secure.LOCATION_MODE);
if (status != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY)
{
return false;
}
}
catch (Settings.SettingNotFoundException e)
{
Log.e(TAG, e.getMessage());
}
}


return true;
}

获取GPS的位置-

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


LocationListener locationListener = 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) {
// TODO Auto-generated method stub
double latitude = location.getLatitude();
double longitude = location.getLongitude();
double speed = location.getSpeed(); //spedd in meter/minute
speed = (speed*3600)/1000;      // speed in km/minute               Toast.makeText(GraphViews.this, "Current speed:" + location.getSpeed(),Toast.LENGTH_SHORT).show();
}
};


locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);


}

您需要使用最新/最新

GoogleApiClient Api

基本上你需要做的是:

private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();

然后

@Override
public void onConnected(Bundle connectionHint) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
}
}

为最准确和可靠的位置。看到我的帖子在这里:

https://stackoverflow.com/a/33599228/2644905

不要使用LocationListener,它不准确并且响应延迟。说实话,这更容易实现。 留档:https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient

LocationManager是一个类,它提供内置方法来获取最后知道的位置

步骤1:创建一个LocationManager对象,如下所示

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

步骤2:添加标准

*Criteria is use for setting accuracy*


Criteria criteria = new Criteria();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;


if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {


criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(true);
criteria.setBearingRequired(true);
criteria.setSpeedRequired(true);


}

步骤3:获取合适的供应商

三种类型的供应商GPS和网络

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

步骤4:最后知道位置

Location location = locationManager.getLastKnownLocation(provider);

步骤5:获取纬度和经度

#EYZ

getLatitude and getLongitude is methods which returns double values

那里已经有很多答案,但我想展示使用Google API获取位置的最新方法,因此新程序员可以使用新方法:

我在我的博客<强>demonuts.com上写了关于在android中的当前位置的详细教程,您还可以找到使用Android Studio开发的完整源代码。

首先把这个放到gradle文件里

 compile 'com.google.android.gms:play-services:9.0.2'

然后实现必要的接口

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

声明实例

  private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private LocationManager locationManager;
private LocationRequest mLocationRequest;

把这个放在onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

最后,覆盖必要的方法

 @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;
} startLocationUpdates();
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。

我做了一个项目,我们可以使用Google Play服务、GPS和网络提供商获得准确的位置。这个项目可以找到这里

找到最佳位置的策略是,如果找到位置,首先从谷歌播放服务获取位置,然后检查天气是否更好,如果找到位置为空,则重新启动谷歌播放服务并尝试从Android位置API获取位置。在更改侦听器上注册位置,当找到更好的位置时,回调将其返回到主要活动。

在代码中使用和实现非常简单,我们只需要嵌入两个类,即LocationManagerInterfaceSmartLocationManagerLocationActivity正在实现接口并使用SmartLocationManager来获取位置。

/**
* Created by Syed Raza Mehdi Naqvi on 8/10/2016.
*/
public interface LocationManagerInterface {
String TAG = LocationManagerInterface.class.getSimpleName();


void locationFetched(Location mLocation, Location oldLocation, String time, String locationProvider);


}

这里是位置管理器类

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;


import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;


import java.text.DateFormat;
import java.util.Date;


/**
* Created by Syed Raza Mehdi Naqvi on 8/9/2016.
*/
public class SmartLocationManager implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {


private static final String TAG = SmartLocationManager.class.getSimpleName();


private static final int TWO_MINUTES = 1000 * 60 * 2;
private static final int PERMISSION_REQUEST_CODE = 1000;
private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;


// default value is false but user can change it
private String mLastLocationUpdateTime;                                                         // fetched location time
private String locationProvider;                                                                // source of fetched location


private Location mLastLocationFetched;                                                          // location fetched
private Location mLocationFetched;                                                              // location fetched
private Location networkLocation;
private Location gpsLocation;


private int mLocationPiority;
private long mLocationFetchInterval;
private long mFastestLocationFetchInterval;


private Context mContext;                                                                       // application context
private Activity mActivity;                                                                     // activity context
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private LocationManagerInterface mLocationManagerInterface;


private android.location.LocationManager locationManager;
private android.location.LocationListener locationListener;


boolean isGPSEnabled;
boolean isNetworkEnabled;


private int mProviderType;
public static final int NETWORK_PROVIDER = 1;
public static final int ALL_PROVIDERS = 0;
public static final int GPS_PROVIDER = 2;


//    private final double STANDARD_LOCATION_ACCURACY = 100.0;
//    private final double STANDARD_LOCATION_SEED_LIMIT = 6.95;


public static final int LOCATION_PROVIDER_ALL_RESTICTION = 1;
public static final int LOCATION_PROVIDER_RESTRICTION_NONE = 0;
public static final int LOCATION_PROVIDER_GPS_ONLY_RESTICTION = 2;
public static final int LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION = 3;
private int mForceNetworkProviders = 0;


public SmartLocationManager(Context context, Activity activity, LocationManagerInterface locationInterface, int providerType, int locationPiority, long locationFetchInterval, long fastestLocationFetchInterval, int forceNetworkProviders) {
mContext = context;
mActivity = activity;
mProviderType = providerType;


mLocationPiority = locationPiority;
mForceNetworkProviders = forceNetworkProviders;
mLocationFetchInterval = locationFetchInterval;
mFastestLocationFetchInterval = fastestLocationFetchInterval;


mLocationManagerInterface = locationInterface;


initSmartLocationManager();
}




public void initSmartLocationManager() {


// 1) ask for permission for Android 6 above to avoid crash
// 2) check if gps is available
// 3) get location using awesome strategy


askLocationPermission();                            // for android version 6 above
checkNetworkProviderEnable(mForceNetworkProviders);                       //


if (isGooglePlayServicesAvailable())                // if googleplay services available
initLocationObjts();                            // init obj for google play service and start fetching location
else
getLocationUsingAndroidAPI();                   // otherwise get location using Android API
}


private void initLocationObjts() {
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(mLocationPiority)
.setInterval(mLocationFetchInterval)                    // 10 seconds, in milliseconds
.setFastestInterval(mFastestLocationFetchInterval);     // 1 second, in milliseconds


if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}


startLocationFetching();                                        // connect google play services to fetch location
}


@Override
public void onConnected(Bundle connectionHint) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
startLocationUpdates();
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
getLocationUsingAndroidAPI();
} else {
setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
}
}


@Override
public void onLocationChanged(Location location) {
if (location == null) {
getLastKnownLocation();
} else {
setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
}
}


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


@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST); // Start an Activity that tries to resolve the error
getLocationUsingAndroidAPI();                                                                // try to get location using Android API locationManager
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}


private void setNewLocation(Location location, Location oldLocation) {
if (location != null) {
mLastLocationFetched = oldLocation;
mLocationFetched = location;
mLastLocationUpdateTime = DateFormat.getTimeInstance().format(new Date());
locationProvider = location.getProvider();
mLocationManagerInterface.locationFetched(location, mLastLocationFetched, mLastLocationUpdateTime, location.getProvider());
}
}


private void getLocationUsingAndroidAPI() {
// Acquire a reference to the system Location Manager
locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);


setLocationListner();
captureLocation();
}


public void captureLocation() {
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
} else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
} else {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}


private void setLocationListner() {
// Define a listener that responds to location updates
locationListener = new android.location.LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
if (location == null) {
getLastKnownLocation();
} else {
setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    if (isLocationAccurate(location) && location.getAccuracy() < STANDARD_LOCATION_ACCURACY && location.getSpeed() < STANDARD_LOCATION_SEED_LIMIT) {// no use of this if
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    } else {
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    }
}
}


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


public void onProviderEnabled(String provider) {
}


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


public Location getAccurateLocation() {
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
}
try {
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Location newLocalGPS, newLocalNetwork;
if (gpsLocation != null || networkLocation != null) {
newLocalGPS = getBetterLocation(mLocationFetched, gpsLocation);
newLocalNetwork = getBetterLocation(mLocationFetched, networkLocation);
setNewLocation(getBetterLocation(newLocalGPS, newLocalNetwork), mLocationFetched);
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
return mLocationFetched;
}


protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}


public void startLocationFetching() {
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}


public void pauseLocationFetching() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}


}


public void abortLocationFetching() {
mGoogleApiClient.disconnect();


// Remove the listener you previously added
if (locationManager != null && locationListener != null) {
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
locationManager.removeUpdates(locationListener);
locationManager = null;
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());


}
}
}


public void resetLocation() {
mLocationFetched = null;
mLastLocationFetched = null;
networkLocation = null;
gpsLocation = null;
}


//  Android M Permission check
public void askLocationPermission() {


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {




if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
|| ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) {


final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setMessage("Please allow all permissions in App Settings for additional functionality.")
.setCancelable(false)
.setPositiveButton("Allow", new DialogInterface.OnClickListener() {
public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
Toast.makeText(mContext, "Welcome", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("Deny", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
mActivity.finish();
}
});
final AlertDialog alert = builder.create();
alert.show();


} else
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
, Manifest.permission.ACCESS_FINE_LOCATION
}, PERMISSION_REQUEST_CODE);


}
}
}


public void checkNetworkProviderEnable(int enforceActive) {
locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);


isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);


if (!isGPSEnabled && !isNetworkEnabled) {
buildAlertMessageTurnOnLocationProviders("Your location providers seems to be disabled, please enable it", "OK", "Cancel");
} else if (!isGPSEnabled && mForceNetworkProviders == LOCATION_PROVIDER_GPS_ONLY_RESTICTION) {
buildAlertMessageTurnOnLocationProviders("Your GPS seems to be disabled, please enable it", "OK", "Cancel");
} else if (!isNetworkEnabled && mForceNetworkProviders == LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION) {
buildAlertMessageTurnOnLocationProviders("Your Network location provider seems to be disabled, please enable it", "OK", "Cancel");
}
// getting network status


if (!isGPSEnabled && !isNetworkEnabled) {
Toast.makeText(mContext, "Location can't be fetched!", Toast.LENGTH_SHORT).show(); // show alert
mActivity.finish();
}
}


private void buildAlertMessageTurnOnLocationProviders(String message, String positiveButtonText, String negativeButtonText) {
final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setMessage(message)
.setCancelable(false)
.setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
Intent mIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(mIntent);
}
})
.setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
mActivity.finish();
}
});
final AlertDialog alert = builder.create();
alert.show();
}




public Location getLastKnownLocation() {
locationProvider = LocationManager.NETWORK_PROVIDER;
Location lastKnownLocation = null;
// Or use LocationManager.GPS_PROVIDER
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return lastKnownLocation;
}
try {
lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
return lastKnownLocation;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return lastKnownLocation;
}


public boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);


if (status == ConnectionResult.SUCCESS) {
return true;
} else {
return false;
}
}


/**
* 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 Location getBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return location;
}


// 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 location;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return currentBestLocation;
}


// 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 location;
} else if (isNewer && !isLessAccurate) {
return location;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return location;
}
return currentBestLocation;
}


/**
* Checks whether two providers are the same
*/


private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}


public boolean isLocationAccurate(Location location) {
if (location.hasAccuracy()) {
return true;
} else {
return false;
}
}


public Location getStaleLocation() {
if (mLastLocationFetched != null) {
return mLastLocationFetched;
}
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
}
if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
} else {
return getBetterLocation(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
}
}
}

我们可以将它与活动或片段一起使用,这里我将它与活动一起使用

import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;


import com.example.raza.locationaware.location.LocationManagerInterface;
import com.example.raza.locationaware.location.SmartLocationManager;
import com.google.android.gms.location.LocationRequest;


public class LocationActivity extends AppCompatActivity implements LocationManagerInterface {


public static final String TAG = LocationActivity.class.getSimpleName();


SmartLocationManager mLocationManager;
TextView mLocalTV, mLocationProviderTV, mlocationTimeTV;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location);
mLocationManager = new SmartLocationManager(getApplicationContext(), this, this, SmartLocationManager.ALL_PROVIDERS, LocationRequest.PRIORITY_HIGH_ACCURACY, 10 * 1000, 1 * 1000, SmartLocationManager.LOCATION_PROVIDER_RESTRICTION_NONE); // init location manager
mLocalTV = (TextView) findViewById(R.id.locationDisplayTV);
mLocationProviderTV = (TextView) findViewById(R.id.locationProviderTV);
mlocationTimeTV = (TextView) findViewById(R.id.locationTimeFetchedTV);
}


protected void onStart() {
super.onStart();
mLocationManager.startLocationFetching();
}


protected void onStop() {
super.onStop();
mLocationManager.abortLocationFetching();
}


@Override
protected void onPause() {
super.onPause();
mLocationManager.pauseLocationFetching();
}


@Override
public void locationFetched(Location mLocal, Location oldLocation, String time, String locationProvider) {
Toast.makeText(getApplication(), "Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude(), Toast.LENGTH_LONG).show();
mLocalTV.setText("Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude());
mLocationProviderTV.setText(locationProvider);
mlocationTimeTV.setText(time);
}
}

希望它能有所帮助,如果你能提出任何改进建议,请将其发布在git上。谢谢。

我发布了一个小型库,可以轻松地在Android中获取位置数据,它甚至可以照顾Android M运行时权限。

您可以在此处查看:https://github.com/julioromano/RxLocation并将其或其源代码用作实现的示例。

获取位置更新需要在Android中大量的bolierboard代码,您需要照顾

  • Google Play服务可用性检查,
  • 更新Google Play服务,如果它旧或不可用
  • 对话框创建GoogleApiClient及其回调连接、断开等。
  • 停止和释放用于位置更新的资源
  • 处理位置权限场景
  • 检查位置服务是否打开或关闭
  • 找到最新的位置也不是那么容易
  • 如果在一定持续时间后没有获得位置,则回退到最后已知位置

为了简化所有这些步骤,我创建了Android-Easy位置(小型Android库),它将处理所有这些内容,您可以专注于业务逻辑。

所有你需要的是扩展EasyLocationActivityActivityActivityActivityActivtionEasyLocationActivityActivityActivityActivityActivityActiveActivityActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActiveActive和这个

requestSingleLocationFix(easyLocationRequest);

requestLocationUpdates(easyLocationRequest);

https://github.com/akhgupta/Android-EasyLocation此处结帐示例应用程序和所需步骤

简单查找就位法中的写代码

public void onLocationChanged(Location location) {
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}




//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
mCurrLocationMarker = mMap.addMarker(markerOptions);


//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(18));


PolylineOptions pOptions = new PolylineOptions()
.width(5)
.color(Color.GREEN)
.geodesic(true);
for (int z = 0; z < routePoints.size(); z++) {
LatLng point = routePoints.get(z);
pOptions.add(point);
}
line = mMap.addPolyline(pOptions);
routePoints.add(latLng);
}

谷歌样本使用最新的FusedLocationProviderApi提供了详细的示例。 不幸的是,投票最多的答案已经过时了。

按照以下示例使用FusedLocationProviderApi实现定位服务

https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java

2022年编辑:不要使用这个,因为那个库有内存泄漏,不再支持/更新。

我建议使用智能位置库
使用非常简单,它很好地包装了位置逻辑。

用于启动位置服务:

SmartLocation.with(context).location()
.start(new OnLocationUpdatedListener() { ... });

如果你只是想获得一个位置(不是周期性的),你可以使用oneFix修饰符。例子:

SmartLocation.with(context).location()
.oneFix()
.start(new OnLocationUpdatedListener() { ... });

我使用融合位置提供商客户端得到了非常准确的位置
需要Google Play服务

是否需要权限

android.permission.ACCESS_FINE_LOCATION

android.permission.ACCESS_COARSE_LOCATION

依赖

'com.google.android.gms:播放服务位置: 15.0.0'

静态编程语言代码

val client = FusedLocationProviderClient(this)
val location = client.lastLocation
location.addOnCompleteListener {
// this is a lambda expression and we get an 'it' iterator to access the 'result'
// it.result.latitude gives the latitude
// it.result.longitude gives the longitude
val geocoder = Geocoder(applicationContext, Locale.getDefault())
val address = geocoder.getFromLocation(it.result.latitude, it.result.longitude, 1)
if (address != null && address.size > 0) {
// Get the current city
city = address[0].locality
}
}
location.addOnFailureListener {
// Some error in getting the location, let's log it
Log.d("xtraces", it.message)
}

获取位置的最佳方式是在下面

// put dependancy
implementation 'com.google.android.gms:play-services-location:11.0.4'


// PUT permissions in Menifest
<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" />




// create a Java file as below


public class SingleShotLocationProvider {


public static interface LocationCallback {
public void onNewLocationAvailable(GPSCoordinates location);
}


// calls back to calling thread, note this is for low grain: if you want higher precision, swap the
// contents of the else and if. Also be sure to check gps permission/settings are allowed.
// call usually takes <10ms


public static void requestSingleUpdate(final Context context, final LocationCallback callback) {
final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isNetworkEnabled) {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {


return;
}
locationManager.requestSingleUpdate(criteria, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
}


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


@Override
public void onProviderEnabled(String provider) {
}


@Override
public void onProviderDisabled(String provider) {
}
}, null);
} else {
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
locationManager.requestSingleUpdate(criteria, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
}


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




// consider returning Location instead of this dummy wrapper class
public static class GPSCoordinates {
public float longitude = -1;
public float latitude = -1;


public GPSCoordinates(float theLatitude, float theLongitude) {
longitude = theLongitude;
latitude = theLatitude;
}


public GPSCoordinates(double theLatitude, double theLongitude) {
longitude = (float) theLongitude;
latitude = (float) theLatitude;
}
}


}
// FILE FINISHED




// FETCH LOCATION FROM ACTIVITY AS BELOW
public void getLocation(Context context) {
MyApplication.log(LOG_TAG, "getLocation() ");


SingleShotLocationProvider.requestSingleUpdate(context,
new SingleShotLocationProvider.LocationCallback() {
@Override
public void onNewLocationAvailable(SingleShotLocationProvider.GPSCoordinates loc) {
location = loc;
MyApplication.log(LOG_TAG, "getLocation() LAT: " + location.latitude + ", LON: " + location.longitude);
}
});
}

2020年4月

获取当前位置的完整步骤,并避免最后已知位置为空。

根据官方留档,在以下情况下,最后已知位置可能是Null

  • 位置在设备设置中被关闭。当它清除 缓存。
  • 设备从未记录其位置。(新设备)
  • 设备上的Google Play服务已重新启动。

在这种情况下,您应该请求位置更新并在位置回调上接收新位置。

通过以下步骤您最后已知的位置永远不会为空。


先决条件: 易权限库


第一步: 在清单文件中添加此权限

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

步骤2:

    override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)


//Create location callback when it's ready.
createLocationCallback()


//createing location request, how mant request would be requested.
createLocationRequest()


//Build check request location setting request
buildLocationSettingsRequest()


//FusedLocationApiClient which includes location
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
//Location setting client
mSettingsClient = LocationServices.getSettingsClient(this)


//Check if you have ACCESS_FINE_LOCATION permission
if (!EasyPermissions.hasPermissions(
this@MainActivity,
Manifest.permission.ACCESS_FINE_LOCATION)) {
requestPermissionsRequired()
}
else{
//If you have the permission we should check location is opened or not
checkLocationIsTurnedOn()
}


}

第三步: 创建要在onCreate()返回值

中调用的所需函数
private fun requestPermissionsRequired() {
EasyPermissions.requestPermissions(
this,
getString(R.string.location_is_required_msg),
LOCATION_REQUEST,
Manifest.permission.ACCESS_FINE_LOCATION
)
}


private fun createLocationCallback() {
//Here the location will be updated, when we could access the location we got result on this callback.
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
mCurrentLocation = locationResult.lastLocation
}
}
}


private fun buildLocationSettingsRequest() {
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(mLocationRequest!!)
mLocationSettingsRequest = builder.build()
builder.setAlwaysShow(true)
}


private fun createLocationRequest() {
mLocationRequest = LocationRequest.create()
mLocationRequest!!.interval = 0
mLocationRequest!!.fastestInterval = 0
mLocationRequest!!.numUpdates = 1
mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}


public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this) {
Log.i(TAG, "All location settings are satisfied.")
startLocationUpdates()
}
.addOnFailureListener(this) { e ->
val statusCode = (e as ApiException).statusCode
when (statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
try {
val rae = e as ResolvableApiException
rae.startResolutionForResult(this@MainActivity, LOCATION_IS_OPENED_CODE)
} catch (sie: IntentSender.SendIntentException) {
}
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
mRequestingLocationUpdates = false
}
}
}
}


private fun startLocationUpdates() {
mFusedLocationClient!!.requestLocationUpdates(
mLocationRequest,
mLocationCallback, null
)
}

步骤4:

onActivityResult()//活动获取//活动获取中处理回调,确保位置已打开或用户接受打开它。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
LOCATION_IS_OPENED_CODE -> {
if (resultCode == AppCompatActivity.RESULT_OK) {
Log.d(TAG, "Location result is OK")
} else {
activity?.finish()
}
}
}

第5步: 从FusedClientApi获取最后已知位置

override fun onMapReady(map: GoogleMap) {
mMap = map
mFusedLocationClient.lastLocation.addOnSuccessListener {
if(it!=null){
locateUserInMap(it)
}
}


}
private fun locateUserInMap(location: Location) {
showLocationSafetyInformation()
if(mMap!=null){
val currentLocation = LatLng(location.latitude,location.longitude )
addMarker(currentLocation)
}
}




private fun addMarker(currentLocation: LatLng) {
val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
mMap?.clear()
mMap?.addMarker(
MarkerOptions().position(currentLocation)
.title("Current Location")
)
mMap?.moveCamera(cameraUpdate)
mMap?.animateCamera(cameraUpdate)
mMap?.setMinZoomPreference(14.0f);
}

我希望这会有帮助。

快乐编码🤓

2020年下半年开始,有一种更简单的方法可以做到这一点。

不包括请求权限(我将在底部包含较新的开发人员),下面是代码。

请记住,您需要在依赖项中至少包含此版本的库(在应用程序的build.gradle中):

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

…当然还有你清单上的许可:

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

静态编程语言(首先设置):

private val fusedLocationClient: FusedLocationProviderClient by lazy {
LocationServices.getFusedLocationProviderClient(applicationContext)
}


private var cancellationTokenSource = CancellationTokenSource()

然后是主代码(对于FINE_LOCATION):

private fun requestCurrentLocation() {
// Check Fine permission
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {


// Main code
val currentLocationTask: Task<Location> = fusedLocationClient.getCurrentLocation(
PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.token
)


currentLocationTask.addOnCompleteListener { task: Task<Location> ->
val result = if (task.isSuccessful) {
val result: Location = task.result
"Location (success): ${result.latitude}, ${result.longitude}"
} else {
val exception = task.exception
"Location (failure): $exception"
}


Log.d(TAG, "getCurrentLocation() result: $result")
}
} else {
// Request fine location permission (full code below).
}

如果你喜欢Java,它看起来像这样:

public class JavaVersion extends AppCompatActivity {


private final String TAG = "MainActivity";


// The Fused Location Provider provides access to location APIs.
private FusedLocationProviderClient fusedLocationClient;


// Allows class to cancel the location request if it exits the activity.
// Typically, you use one cancellation source per lifecycle.
private final CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
...
    

private void requestCurrentLocation() {
Log.d(TAG, "requestCurrentLocation()");
// Request permission
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
            

// Main code
Task<Location> currentLocationTask = fusedLocationClient.getCurrentLocation(
PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.getToken()
);


currentLocationTask.addOnCompleteListener((new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {


String result = "";


if (task.isSuccessful()) {
// Task completed successfully
Location location = task.getResult();
result = "Location (success): " +
location.getLatitude() +
", " +
location.getLongitude();
} else {
// Task failed with an exception
Exception exception = task.getException();
result = "Exception thrown: " + exception;
}


Log.d(TAG, "getCurrentLocation() result: " + result);
}
}));
} else {
// TODO: Request fine location permission
Log.d(TAG, "Request fine location permission.");
}
}
...
}

论据:

  1. 优先级类型是不言自明的。(其他选项是PRIORITY_BALANCED_POWER_ACCURACY、PRIORITY_LOW_POWER和PRIORITY_NO_POWER。)
  2. 取消订单-这允许您取消请求,例如,如果用户导航离开您的活动。

示例(静态编程语言):

override fun onStop() {
super.onStop()
// Cancels location request (if in flight).
cancellationTokenSource.cancel()
}

就这样了。

现在,这确实使用了融合位置提供商客户端,它是一个Google Play服务API。

这意味着这适用于所有带有谷歌应用商店的Android设备(其中很多)。然而,对于没有Play商店的中国设备,这将不起作用,所以要考虑到这一点。

对于对此稍新的开发人员,如果用户尚未批准,则需要请求精细(或粗略)位置权限,因此在上面的代码中,我会请求位置权限。

下面是完整的代码(静态编程语言)。

我希望这能帮助你(让你的生活更轻松)!

/**
* Demonstrates how to easily get the current location via the [FusedLocationProviderClient.getCurrentLocation].
* The main code is in this class's requestCurrentLocation() method.
*/
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding


// The Fused Location Provider provides access to location APIs.
private val fusedLocationClient: FusedLocationProviderClient by lazy {
LocationServices.getFusedLocationProviderClient(applicationContext)
}


// Allows class to cancel the location request if it exits the activity.
// Typically, you use one cancellation source per lifecycle.
private var cancellationTokenSource = CancellationTokenSource()


// If the user denied a previous permission request, but didn't check "Don't ask again", this
// Snackbar provides an explanation for why user should approve, i.e., the additional rationale.
private val fineLocationRationalSnackbar by lazy {
Snackbar.make(
binding.container,
R.string.fine_location_permission_rationale,
Snackbar.LENGTH_LONG
).setAction(R.string.ok) {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE
)
}
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)


binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root


setContentView(view)
}


override fun onStop() {
super.onStop()
// Cancels location request (if in flight).
cancellationTokenSource.cancel()
}


override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
Log.d(TAG, "onRequestPermissionResult()")


if (requestCode == REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE) {
when {
grantResults.isEmpty() ->
// If user interaction was interrupted, the permission request
// is cancelled and you receive an empty array.
Log.d(TAG, "User interaction was cancelled.")


grantResults[0] == PackageManager.PERMISSION_GRANTED ->
Snackbar.make(
binding.container,
R.string.permission_approved_explanation,
Snackbar.LENGTH_LONG
)
.show()


else -> {
Snackbar.make(
binding.container,
R.string.fine_permission_denied_explanation,
Snackbar.LENGTH_LONG
)
.setAction(R.string.settings) {
// Build intent that displays the App settings screen.
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri = Uri.fromParts(
"package",
BuildConfig.APPLICATION_ID,
null
)
intent.data = uri
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
.show()
}
}
}
}


fun locationRequestOnClick(view: View) {
Log.d(TAG, "locationRequestOnClick()")


requestCurrentLocation()
}


/**
* Gets current location.
* Note: The code checks for permission before calling this method, that is, it's never called
* from a method with a missing permission. Also, I include a second check with my extension
* function in case devs just copy/paste this code.
*/
private fun requestCurrentLocation() {
Log.d(TAG, "requestCurrentLocation()")
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {


// Returns a single current location fix on the device. Unlike getLastLocation() that
// returns a cached location, this method could cause active location computation on the
// device. A single fresh location will be returned if the device location can be
// determined within reasonable time (tens of seconds), otherwise null will be returned.
//
// Both arguments are required.
// PRIORITY type is self-explanatory. (Other options are PRIORITY_BALANCED_POWER_ACCURACY,
// PRIORITY_LOW_POWER, and PRIORITY_NO_POWER.)
// The second parameter, [CancellationToken] allows the activity to cancel the request
// before completion.
val currentLocationTask: Task<Location> = fusedLocationClient.getCurrentLocation(
PRIORITY_HIGH_ACCURACY,
cancellationTokenSource.token
)


currentLocationTask.addOnCompleteListener { task: Task<Location> ->
val result = if (task.isSuccessful) {
val result: Location = task.result
"Location (success): ${result.latitude}, ${result.longitude}"
} else {
val exception = task.exception
"Location (failure): $exception"
}


Log.d(TAG, "getCurrentLocation() result: $result")
logOutputToScreen(result)
}
} else {
val provideRationale = shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)


if (provideRationale) {
fineLocationRationalSnackbar.show()
} else {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE)
}
}
}


private fun logOutputToScreen(outputString: String) {
val finalOutput = binding.outputTextView.text.toString() + "\n" + outputString
binding.outputTextView.text = finalOutput
}


companion object {
private const val TAG = "MainActivity"
private const val REQUEST_FINE_LOCATION_PERMISSIONS_REQUEST_CODE = 34
}
}

由于2020年9月23日 play-services-place版本17.1.0包含FusedLocationProviderClient.get当前位置方法,这是获取当前位置的推荐且直接的方法:

返回设备上的单个当前位置修复。与返回缓存位置的获取当前位置不同,此方法可能会导致设备上的活动位置计算。如果可以在合理时间内(数十秒)确定设备位置,则将返回单个新鲜位置,否则将返回null。

有关详细示例,请查看GitHub上的杰里米的回答和官方Android位置示例-当前位置(静态编程语言)