如何修复 'GPS unable to get Location'?
How to fix 'GPS unable to get Location'?
我正在创建一个 Android 应用程序来获取我当前的 GPS 位置。一开始它在工作,但现在它总是 returns null。它只是在我的 phone 的通知栏中显示 GPS 图标,但该图标未被激活或突出显示。我尝试了很多技巧,但到目前为止没有任何效果。这是我的代码:
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@SuppressLint("RestrictedApi")
@Override
public void onClick(View view) {
fab.setVisibility(View.VISIBLE);
GpsTracker gt = new GpsTracker(getApplicationContext());
Location l = gt.getLocation();
if(l != null) {
double lat = l.getLatitude();
double lon = l.getLongitude();
Toast.makeText(getApplicationContext(),"GPS Lat = "+lat+"\n lon = "+lon,Toast.LENGTH_SHORT).show();
Snackbar.make(view, "GPS Lat = "+lat+"\n lon = "+lon, Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
} else {
Snackbar.make(view, "GPS unable to Connect", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
Toast.makeText(getApplicationContext(),"GPS unable to Connect",Toast.LENGTH_SHORT).show();
}
}
});
GpsTracker.java
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import static android.content.Context.LOCATION_SERVICE;
public class GpsTracker implements LocationListener {
public Context context;
public GpsTracker(Context context) {
super();
this.context = context;
}
public Location getLocation(){
if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
Log.e("fist","error");
return null;
}
try {
LocationManager lm = (LocationManager) context.getSystemService(LOCATION_SERVICE);
boolean isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000,10,this);
Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
return loc;
} else {
Log.e("sec","Please enable your GPS");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
您只是在访问最后一个已知位置。对于您当前的位置,这通常是空的或非常不准确。您应该等到从 onLocationChanged 获得一些成功的读数,然后再 return 向调用者发送一个值。
也许您应该将初始化位置管理器的代码拆分成一个方法,startLocationTracking()。然后,在您的代码中,在首次创建 Action/Fragment 时调用它。一旦位置管理器获得 onLocationChanged 事件,它将使用当前位置更新 Public 变量。然后,您的 getLocation() 方法会将 currentLocation 变量简单地 return 给调用者。然后,您可能应该有一个在 Action/Fragment 关闭时调用的 stopLocationTracking() 方法。
哈桑,
您是否考虑过使用 Google 服务来检索自己的位置。我更喜欢用那个。下面是一个示例,但是您需要
- 第一步
在 Google API 控制台上设置 Google API 键:https://console.developers.google.com/?pli=1
为 Android 选择 Maps SDK 并启用它,然后在其中生成 API 密钥。
- 第二步
将 API 键复制并粘贴到项目 strings.xml 文件中
- 第三步
在您的 app.gradle 文件中添加以下依赖项
implementation 'com.google.android.gms:play-services-maps:16.1.0'
- 第四步
在您的 AndroidManifest.xml 中,在应用程序标签
之后添加以下内容
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/google_maps_key" />
- 第五步
执行以下类
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
/*Declare the following Variables */
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private boolean mRequestingLocationUpdates = false;
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
public GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
Location mLastLocation;
public static double lat = 0, lng = 0;
LocationManager locationManager;
Location location = null;
- 第六步
在 OnCreate 函数之外创建以下函数
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
@SuppressLint("MissingPermission")
protected void startLocationUpdates() {
try {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (LocationListener) this);
} catch (Exception e) {
Log.d("LOCATION_MSG", e.getMessage());
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (LocationListener) this);
}
- 第七步
在 onCreate
中调用构建GoogleApiClient()
- 第八步
覆盖方法
@Override
public void onConnected(@Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@SuppressLint("MissingPermission")
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
@Override
public void onMapReady(GoogleMap googleMap) {
}
- 第九步
在您的 OnClick 侦听器中:
fab.setOnClickListener
添加这个
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
startLocationUpdates();
if (mLastLocation != null)
{
try {
lat = mLastLocation.getLatitude();
lng = mLastLocation.getLongitude();
} catch (Exception e) {
lat = 0;
lng = 0;
}
/* Check your log cat for the following */
Log.d("LOC_Latitude" , Double.toString(lat));
Log.d("LOC_Longitude" , Double.toString(lng));
}else{
//Something is a miss, maybe the location service on your phone is not on, it could even be the internet connection.
}
注意事项
确保您拥有清单上的所有先决条件权限,某些设备需要在 运行 时间请求权限。您可以使用以下方法来做到这一点
/*在我们的 onCreate 函数之外声明这个方法 */
public static boolean hasPermissions(Context context, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
/*Add this in your onCreate Function */
String[] PERMISSIONS = {Manifest.permission.INTERNET, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 1);
}
还要确保您对 AndroidManifest.xml
具有以下权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
尝试一下并在任何情况下恢复你仍然卡住。
我正在创建一个 Android 应用程序来获取我当前的 GPS 位置。一开始它在工作,但现在它总是 returns null。它只是在我的 phone 的通知栏中显示 GPS 图标,但该图标未被激活或突出显示。我尝试了很多技巧,但到目前为止没有任何效果。这是我的代码:
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@SuppressLint("RestrictedApi")
@Override
public void onClick(View view) {
fab.setVisibility(View.VISIBLE);
GpsTracker gt = new GpsTracker(getApplicationContext());
Location l = gt.getLocation();
if(l != null) {
double lat = l.getLatitude();
double lon = l.getLongitude();
Toast.makeText(getApplicationContext(),"GPS Lat = "+lat+"\n lon = "+lon,Toast.LENGTH_SHORT).show();
Snackbar.make(view, "GPS Lat = "+lat+"\n lon = "+lon, Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
} else {
Snackbar.make(view, "GPS unable to Connect", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
Toast.makeText(getApplicationContext(),"GPS unable to Connect",Toast.LENGTH_SHORT).show();
}
}
});
GpsTracker.java
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import static android.content.Context.LOCATION_SERVICE;
public class GpsTracker implements LocationListener {
public Context context;
public GpsTracker(Context context) {
super();
this.context = context;
}
public Location getLocation(){
if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) {
Log.e("fist","error");
return null;
}
try {
LocationManager lm = (LocationManager) context.getSystemService(LOCATION_SERVICE);
boolean isGPSEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000,10,this);
Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
return loc;
} else {
Log.e("sec","Please enable your GPS");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
您只是在访问最后一个已知位置。对于您当前的位置,这通常是空的或非常不准确。您应该等到从 onLocationChanged 获得一些成功的读数,然后再 return 向调用者发送一个值。
也许您应该将初始化位置管理器的代码拆分成一个方法,startLocationTracking()。然后,在您的代码中,在首次创建 Action/Fragment 时调用它。一旦位置管理器获得 onLocationChanged 事件,它将使用当前位置更新 Public 变量。然后,您的 getLocation() 方法会将 currentLocation 变量简单地 return 给调用者。然后,您可能应该有一个在 Action/Fragment 关闭时调用的 stopLocationTracking() 方法。
哈桑,
您是否考虑过使用 Google 服务来检索自己的位置。我更喜欢用那个。下面是一个示例,但是您需要
- 第一步
在 Google API 控制台上设置 Google API 键:https://console.developers.google.com/?pli=1
为 Android 选择 Maps SDK 并启用它,然后在其中生成 API 密钥。
- 第二步
将 API 键复制并粘贴到项目 strings.xml 文件中
- 第三步
在您的 app.gradle 文件中添加以下依赖项
implementation 'com.google.android.gms:play-services-maps:16.1.0'
- 第四步
在您的 AndroidManifest.xml 中,在应用程序标签
之后添加以下内容<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/google_maps_key" />
- 第五步
执行以下类
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
/*Declare the following Variables */
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private boolean mRequestingLocationUpdates = false;
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters
public GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
Location mLastLocation;
public static double lat = 0, lng = 0;
LocationManager locationManager;
Location location = null;
- 第六步
在 OnCreate 函数之外创建以下函数
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
@SuppressLint("MissingPermission")
protected void startLocationUpdates() {
try {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (LocationListener) this);
} catch (Exception e) {
Log.d("LOCATION_MSG", e.getMessage());
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (LocationListener) this);
}
- 第七步
在 onCreate
中调用构建GoogleApiClient()- 第八步
覆盖方法
@Override
public void onConnected(@Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@SuppressLint("MissingPermission")
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
@Override
public void onMapReady(GoogleMap googleMap) {
}
- 第九步
在您的 OnClick 侦听器中:
fab.setOnClickListener
添加这个
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
startLocationUpdates();
if (mLastLocation != null)
{
try {
lat = mLastLocation.getLatitude();
lng = mLastLocation.getLongitude();
} catch (Exception e) {
lat = 0;
lng = 0;
}
/* Check your log cat for the following */
Log.d("LOC_Latitude" , Double.toString(lat));
Log.d("LOC_Longitude" , Double.toString(lng));
}else{
//Something is a miss, maybe the location service on your phone is not on, it could even be the internet connection.
}
注意事项 确保您拥有清单上的所有先决条件权限,某些设备需要在 运行 时间请求权限。您可以使用以下方法来做到这一点
/*在我们的 onCreate 函数之外声明这个方法 */
public static boolean hasPermissions(Context context, String... permissions) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) { for (String permission : permissions) { if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } } return true; } /*Add this in your onCreate Function */ String[] PERMISSIONS = {Manifest.permission.INTERNET, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; if (!hasPermissions(this, PERMISSIONS)) { ActivityCompat.requestPermissions(this, PERMISSIONS, 1); }
还要确保您对 AndroidManifest.xml
具有以下权限<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
尝试一下并在任何情况下恢复你仍然卡住。