我遇到问题,如果我的手机的位置服务已关闭,我想设置一个提醒,打开位置服务设置并在那里打开它。这工作正常,但问题是我打开后导航回我的应用程序。好像当我点击回来时,我的活动的onResume
被调用,但在onResume
完成之前,该位置仍未正确设置。这是我的代码:
Comments.java:
@Override
public void onResume() {
super.onResume();
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
Location location = LocationService.getLastLocation();
if(location == null) {
if(getLastKnownLocation() == null) {
if(checkLocationEnabled()); {
location = getLastKnownLocation();
}
}
}
if(location != null) {
progressOverlay = fragmentView.findViewById(R.id.progress_overlay);
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.9f, 200);
//Within this function call, the progress overlay is set to View.GONE.
databaseQuery.getPublicPosts(location, progressOverlay, fragmentView, getContext());
} else {
//We need to handle an error saying that location is not enabled for this device and exit them out of the app
}
}
private Location getLastKnownLocation() {
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
Location bestLocation = null;
for (String provider : providers) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return null;
} else {
Location l = locationManager.getLastKnownLocation(provider);
if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
// Found best last known location: %s", l);
bestLocation = l;
}
}
}
return bestLocation;
}
public boolean checkLocationEnabled() {
try {
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch(Exception ex) {
}
try {
network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch(Exception ex) {
}
if(!gps_enabled && !network_enabled) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
dialog.setMessage(getContext().getResources().getString(R.string.gpsNetworkNotEnabled));
dialog.setPositiveButton(getContext().getResources().getString(R.string.openLocationSettings), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
getContext().startActivity(myIntent);
//get gps
}
});
dialog.setNegativeButton(getContext().getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
}
});
dialog.show();
}
return gps_enabled || network_enabled;
}
我所做的是当电话位置服务关闭时,我设置了一个警报,将您带到位置服务屏幕。当用户打开位置服务屏幕时,如果他或她点击他或她的电话上的“后退”,则应将他们带回到初始屏幕,该屏幕显示他们的位置服务处于警戒状态。但是,当导航回该屏幕时,我的progressOverlay
变量仍然可见,因为当progressOverlay
来电时,View.GONE
设置为databaseQuery.getPublicPosts
。这似乎不会发生,因为当我们导航回屏幕时if(location != null)
语句可能是错误的,但是在电话等待几秒钟并完全获得电话位置后可能设置为true。这很有意思,因为如果我将调试器放在该代码的任何位置,那么位置服务将被正确设置,我的progressOverlay
将会消失,因为在调试代码时该位置已设置。在调用databaseQuery.getPublicPosts
之前,有没有办法可以“等待”或继续显示加载屏幕,直到位置服务完全打开?任何帮助将不胜感激。
答案 0 :(得分:1)
首先,if(checkLocationEnabled());
中有一个不需要的分号,它作为一个空语句,导致第二次调用getLastKnownLocation()
始终执行(这很可能不会影响问题)。
LocationManager
类有一个常量KEY_STATUS_CHANGED
,它是广播状态更改时传递的附加包的关键。请参阅与常量相关的文档。要触发此更改,您需要调用[LocationManager.requestLocationUpdates
](https://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long,float,android.location.Criteria,android.app.PendingIntent)),以便位置管理器收到此类状态更新。
从此方法的文档中,您可以使用BroadcastReceiver
通过过滤上述常量来接收更新。 Here是执行此操作的相关帖子。或者,您可以使用另一个重载版本的请求更新方法,该方法会LocationListener
进行onStatusChanged
回调。
使用KEY_PROVIDER_ENABLED
启用位置提供程序时,存在类似的更新。如果状态更新不起作用,您可以尝试侦听这两个更新。
请注意,在为提供商请求位置更新时,为了包括所有提供商的更新(包括已禁用),您应该使用LocationManager.getProviders(false)
检索它们。
收到相应的更新事件后,您可以致电removeUpdates
删除更新请求。
答案 1 :(得分:1)
为什么要尝试使用 getLastKnownLocation 。它会返回您之前的纬度和经度,并且可能需要一些时间来更新上次知道的位置。 很可能它会在您所在位置后退回null。
我只是引用你 google Fused api 获取任何类型的更新或当前位置。它非常准确。
如何在项目中融合api。请参阅我的小例子。
步骤1.将此类设为GoogleLocationService.java
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 30000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
@Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
<强>第二步。制作这个界面 LocationUpdateListener.java 强>
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* @param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* @param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
步骤3.在想要获取位置的地方使用这段代码
public class MainActivity extends ActionBarActivity {
private GoogleLocationService googleLocationService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
@Override
public void canReceiveLocationUpdates() {
}
@Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
@Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
@Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
}
@Override
public void onDestroy() {
super.onDestroy();
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
}
}
更新回答 如何通过广播发送和接收lat lng
称之为onlocationchanged
Intent sendBroadIntentPND = new Intent("COORD_BROADCAST_FILTER");
sendBroadIntentPND.putExtra("LOC_LAT", location.getLatitude());
sendBroadIntentPND.putExtra("LOC_LON", location.getLongitude());
getApplicationContext().sendBroadcast(sendBroadIntentPND);
然后你想以这种方式接收位置调用
// declear global variable
private final String COORD_BROADCAST_FILTER = "COORD_BROADCAST_FILTER";
private Location newLocation;
private BroadcastReceiver coordinateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
newLocation.setLatitude(intent.getDoubleExtra("LOC_LAT", 0.0));
newLocation.setLongitude(intent.getDoubleExtra("LOC_LON", 0.0));
} catch (Exception e) {
e.printStackTrace();
}
}
};
注册接收者oncreate,
getActivity().registerReceiver(coordinateReceiver, new IntentFilter(COORD_BROADCAST_FILTER));
取消注册您的接收器ondestroy
getActivity().unregisterReceiver(coordinateReceiver);
谢谢希望这对你有所帮助。
答案 2 :(得分:0)
请注意
Google Play服务位置API优于Android 框架位置API(android.location)作为添加位置的一种方式 了解您的应用。如果您目前正在使用Android 框架位置API,强烈建议您切换到 Google Play尽快提供服务位置API。