Android 无法获取我的 GPS 位置 - 一直在等待 GPS
Android can't get my GPS location - stuck on waiting for GPS
我知道这是一个经常被讨论的领域,但在我的应用程序中我无法再获取用户的位置。它适用于我当前的代码,但我只是关闭然后重新打开我设备上的 GPS,从那时起应用程序无法获取我的位置。一些用户也反映,该应用无法再获取他们的位置。
代码很长,我会尽量把重要的部分放在这里:
定义参数:
private final static int ALL_PERMISSIONS_RESULT = 101;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 60000; //1.0 mins
LocationManager locationManager;Location loc;
ArrayList<String> permissions = new ArrayList<>();
ArrayList permissionsToRequest;
ArrayList<String> permissionsRejected = new ArrayList<>();
boolean isGPS = false; boolean isNetwork = false; boolean canGetLocation = true;
在 onCreate() 中:
locationManager = (LocationManager) this.getSystemService(Service.LOCATION_SERVICE);
assert locationManager != null;
isGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
permissionsToRequest = findUnAskedPermissions(permissions);
if (!isGPS && !isNetwork) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
showSettingsAlert();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
getLastLocation();
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (permissionsToRequest.size() > 0) {
requestPermissions((String[]) permissionsToRequest.toArray(new String[0]),
ALL_PERMISSIONS_RESULT);
canGetLocation = false;
}
}
getLocation();
}
其他部分代码:
@Override
public void onLocationChanged(Location location) {updateUI(location);}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {}
@Override
public void onProviderEnabled(String s) {
getLocation();
}
@Override
public void onProviderDisabled(String s) {
if (locationManager != null) {
locationManager.removeUpdates(this);
}
}
getLocation method:
private void getLocation() {
try {
if (canGetLocation) {
if (isGPS) {
Log.e("GPS", String.valueOf(isGPS));
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else if (isNetwork) { Log.e("isNetwork", String.valueOf(isNetwork));
// from Network Provider
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else {
loc.setLatitude(0);
loc.setLongitude(0);
updateUI(loc);
}
} else {Toast.makeText(this, R.string.nolocation,Toast.LENGTH_LONG).show();}
} catch (SecurityException e) {
e.printStackTrace();}
}
private void getLocation() {
try {
if (canGetLocation) {
if (isGPS) {
Log.e("GPS", String.valueOf(locationManager));
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else if (isNetwork) { Log.e("isNetwork", String.valueOf(isNetwork));
// from Network Provider
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else { Log.e("aaaaaa", "sssss");
loc.setLatitude(0);
loc.setLongitude(0);
updateUI(loc);
}
} else {Toast.makeText(this, R.string.nolocation,Toast.LENGTH_LONG).show();}
} catch (SecurityException e) {
e.printStackTrace();}
}
private void getLastLocation() {
try {
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
if(provider==null) { if (dialog != null) {
dialog.dismiss();
dialog = null;
} showSettingsAlert(); if (dialog != null) {
dialog.dismiss();
dialog = null;
}}
else {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {updateUI(location);}
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
private ArrayList findUnAskedPermissions(ArrayList<String> wanted) {
ArrayList<String> result = new ArrayList<>();
for (String perm : wanted) {
if (!hasPermission(perm)) {
result.add(perm);
}
}
return result;
}
private boolean hasPermission(String permission) {
if (canAskPermission()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (this.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
}
}
return true;
}
private boolean canAskPermission() {
return true;
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == ALL_PERMISSIONS_RESULT) {
for (Object perms : permissionsToRequest) {
if (!hasPermission((String) perms)) {
permissionsRejected.add((String) perms);
}
}
if (permissionsRejected.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
showMessageOKCancel(getString(R.string.denied),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsRejected.toArray(
new String[0]), ALL_PERMISSIONS_RESULT);
}
});
}
}
} else {
canGetLocation = true;
getLocation();
}
}
}
public void showSettingsAlert() { if (dialog != null) {
dialog.dismiss();
dialog = null; }
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert);
alertDialog.setTitle(R.string.nogps);
alertDialog.setMessage(R.string.askgps);
alertDialog.setPositiveButton(R.string.ano, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { dialog.dismiss();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
isFromSetting = true;
startActivity(intent);
}
});
alertDialog.setNegativeButton(R.string.nie, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton(R.string.cancel, null)
.create()
.show(); }
public void updateUI(Location loc) {
double Act1=loc.getLatitude();
double Act2=loc.getLongitude();
adapter.clear();adapter.notifyDataSetChanged();
TextView listTitle = findViewById(R.id.booklist_title1);
ListView lv = findViewById(R.id.listViewx);
if (Act1 > 0.0) { listTitle.setVisibility(View.GONE);lv.setVisibility(View.VISIBLE);
Object[] obj = new Object[3];obj[0] = Act1;obj[1] = Act2;
new GetContacts(Okoli.this).execute(obj);
} else {
listTitle.setVisibility(View.VISIBLE);listTitle.setText(R.string.waitGPS);lv.setVisibility(View.GONE);
}
}
当我调试它时,if (isGPS) {Log.e("GPS", String.valueOf(isGPS));...然后我看到 isGPS 是真的,但我等了已经 30 分钟了,我设备上的位置图标还在,但是没有任何反应,似乎无法获取我的位置了。
当然是通过权限等搞定的,至少我知道,getLocation
方法是启动的,因为我把Log放在那里了
然后我也发现,在这个:
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Log.e("loc", String.valueOf(loc));
if (loc != null) {updateUI(loc);}
}
loc为空,所以没有调用updateUI
在我重新安装应用程序后,位置突然起作用了,但是如果我关闭并打开我的位置,我可以等待一个小时,但什么也没有发生。
所以现在我调换了顺序,所以首先我调用 isNetwork,然后才调用 isGPS,这样它工作得比较好。问题似乎出在 GPS 中,其中 getLastKnownLocation 给出 null 并且需要很长时间才能出现 requestLocationUpdates。
但是不确定,与 GPS 相比,网络提供商的位置有多准确
我知道这是一个经常被讨论的领域,但在我的应用程序中我无法再获取用户的位置。它适用于我当前的代码,但我只是关闭然后重新打开我设备上的 GPS,从那时起应用程序无法获取我的位置。一些用户也反映,该应用无法再获取他们的位置。
代码很长,我会尽量把重要的部分放在这里:
定义参数:
private final static int ALL_PERMISSIONS_RESULT = 101;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 60000; //1.0 mins
LocationManager locationManager;Location loc;
ArrayList<String> permissions = new ArrayList<>();
ArrayList permissionsToRequest;
ArrayList<String> permissionsRejected = new ArrayList<>();
boolean isGPS = false; boolean isNetwork = false; boolean canGetLocation = true;
在 onCreate() 中:
locationManager = (LocationManager) this.getSystemService(Service.LOCATION_SERVICE);
assert locationManager != null;
isGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
permissionsToRequest = findUnAskedPermissions(permissions);
if (!isGPS && !isNetwork) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
showSettingsAlert();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
getLastLocation();
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (permissionsToRequest.size() > 0) {
requestPermissions((String[]) permissionsToRequest.toArray(new String[0]),
ALL_PERMISSIONS_RESULT);
canGetLocation = false;
}
}
getLocation();
}
其他部分代码:
@Override
public void onLocationChanged(Location location) {updateUI(location);}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {}
@Override
public void onProviderEnabled(String s) {
getLocation();
}
@Override
public void onProviderDisabled(String s) {
if (locationManager != null) {
locationManager.removeUpdates(this);
}
}
getLocation method:
private void getLocation() {
try {
if (canGetLocation) {
if (isGPS) {
Log.e("GPS", String.valueOf(isGPS));
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else if (isNetwork) { Log.e("isNetwork", String.valueOf(isNetwork));
// from Network Provider
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else {
loc.setLatitude(0);
loc.setLongitude(0);
updateUI(loc);
}
} else {Toast.makeText(this, R.string.nolocation,Toast.LENGTH_LONG).show();}
} catch (SecurityException e) {
e.printStackTrace();}
}
private void getLocation() {
try {
if (canGetLocation) {
if (isGPS) {
Log.e("GPS", String.valueOf(locationManager));
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else if (isNetwork) { Log.e("isNetwork", String.valueOf(isNetwork));
// from Network Provider
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else { Log.e("aaaaaa", "sssss");
loc.setLatitude(0);
loc.setLongitude(0);
updateUI(loc);
}
} else {Toast.makeText(this, R.string.nolocation,Toast.LENGTH_LONG).show();}
} catch (SecurityException e) {
e.printStackTrace();}
}
private void getLastLocation() {
try {
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
if(provider==null) { if (dialog != null) {
dialog.dismiss();
dialog = null;
} showSettingsAlert(); if (dialog != null) {
dialog.dismiss();
dialog = null;
}}
else {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {updateUI(location);}
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
private ArrayList findUnAskedPermissions(ArrayList<String> wanted) {
ArrayList<String> result = new ArrayList<>();
for (String perm : wanted) {
if (!hasPermission(perm)) {
result.add(perm);
}
}
return result;
}
private boolean hasPermission(String permission) {
if (canAskPermission()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (this.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
}
}
return true;
}
private boolean canAskPermission() {
return true;
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == ALL_PERMISSIONS_RESULT) {
for (Object perms : permissionsToRequest) {
if (!hasPermission((String) perms)) {
permissionsRejected.add((String) perms);
}
}
if (permissionsRejected.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
showMessageOKCancel(getString(R.string.denied),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsRejected.toArray(
new String[0]), ALL_PERMISSIONS_RESULT);
}
});
}
}
} else {
canGetLocation = true;
getLocation();
}
}
}
public void showSettingsAlert() { if (dialog != null) {
dialog.dismiss();
dialog = null; }
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert);
alertDialog.setTitle(R.string.nogps);
alertDialog.setMessage(R.string.askgps);
alertDialog.setPositiveButton(R.string.ano, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { dialog.dismiss();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
isFromSetting = true;
startActivity(intent);
}
});
alertDialog.setNegativeButton(R.string.nie, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton(R.string.cancel, null)
.create()
.show(); }
public void updateUI(Location loc) {
double Act1=loc.getLatitude();
double Act2=loc.getLongitude();
adapter.clear();adapter.notifyDataSetChanged();
TextView listTitle = findViewById(R.id.booklist_title1);
ListView lv = findViewById(R.id.listViewx);
if (Act1 > 0.0) { listTitle.setVisibility(View.GONE);lv.setVisibility(View.VISIBLE);
Object[] obj = new Object[3];obj[0] = Act1;obj[1] = Act2;
new GetContacts(Okoli.this).execute(obj);
} else {
listTitle.setVisibility(View.VISIBLE);listTitle.setText(R.string.waitGPS);lv.setVisibility(View.GONE);
}
}
当我调试它时,if (isGPS) {Log.e("GPS", String.valueOf(isGPS));...然后我看到 isGPS 是真的,但我等了已经 30 分钟了,我设备上的位置图标还在,但是没有任何反应,似乎无法获取我的位置了。
当然是通过权限等搞定的,至少我知道,getLocation
方法是启动的,因为我把Log放在那里了
然后我也发现,在这个:
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Log.e("loc", String.valueOf(loc));
if (loc != null) {updateUI(loc);}
}
loc为空,所以没有调用updateUI
在我重新安装应用程序后,位置突然起作用了,但是如果我关闭并打开我的位置,我可以等待一个小时,但什么也没有发生。
所以现在我调换了顺序,所以首先我调用 isNetwork,然后才调用 isGPS,这样它工作得比较好。问题似乎出在 GPS 中,其中 getLastKnownLocation 给出 null 并且需要很长时间才能出现 requestLocationUpdates。
但是不确定,与 GPS 相比,网络提供商的位置有多准确