通过定位服务警报开启定位后等待定位开启
Posted
技术标签:
【中文标题】通过定位服务警报开启定位后等待定位开启【英文标题】:Waiting until location is on after turning it on through location services alert 【发布时间】:2017-01-17 07:43:31 【问题描述】:我遇到的问题是,如果我的手机的定位服务已关闭,我想设置一个警报以打开定位服务设置并将其打开。这工作正常,但问题是当我打开它后导航回我的应用程序时。似乎当我单击返回时,我的活动的onResume
被调用,但在onResume
完成之前,该位置仍未正确设置。这是我的代码:
评论.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
变量仍然可见,因为当 databaseQuery.getPublicPosts
调用通过时,progressOverlay
设置为 View.GONE
。这似乎没有发生,因为当我们导航回屏幕时,if(location != null)
语句可能是错误的,但在手机等待几秒钟并完全获取手机的位置后可能设置为 true。这很有趣,因为如果我在该代码中的任何位置放置调试器,位置服务将被正确设置,而我的progressOverlay
将消失,因为在我调试代码时位置已设置。在调用databaseQuery.getPublicPosts
之前,我有什么方法可以“等待”或继续显示加载屏幕,直到位置服务完全开启?任何帮助将不胜感激。
【问题讨论】:
你的问题解决了吗? 【参考方案1】:嗨,为什么要尝试使用 getLastKnownLocation。它会返回您之前的纬度和经度,并且可能需要一些时间来更新 lastknownLocation。 很可能它会在您的位置返回 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();
;
在创建时注册你的接收器,
getActivity().registerReceiver(coordinateReceiver, new IntentFilter(COORD_BROADCAST_FILTER));
在销毁时取消注册您的接收器
getActivity().unregisterReceiver(coordinateReceiver);
谢谢,希望对你有帮助。
【讨论】:
我应该把第三段代码放在我想要获取位置的地方吗?我只是在onResume()
中调用startUpdates
吗?
确定不是问题,慢慢来
不只是把它放到oncreate中。等一下,我会编辑我的答案
好的,让我试试这个。给我几分钟
请检查您缺少的东西【参考方案2】:
首先,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 是一个相关的帖子。或者,您可以使用另一个重载版本的请求更新方法,该方法采用具有 onStatusChanged
回调的 LocationListener
。
在启用位置提供程序时存在类似的更新,KEY_PROVIDER_ENABLED
。如果状态更新不起作用,您可以尝试监听这两个更新。
请注意,在为提供者请求位置更新时,为了包含所有提供者的更新,包括已禁用的,您应该使用LocationManager.getProviders(false)
检索它们。
收到相应的更新事件后,您可以致电removeUpdates
删除更新请求。
【讨论】:
【参考方案3】:请注意
Google Play 服务位置 API 优于 Android 框架位置 API (android.location) 作为添加位置的一种方式 对您的应用的认识。如果您当前使用的是安卓 框架位置 API,强烈建议您切换到 尽快提供 Google Play 服务位置 API。
【讨论】:
以上是关于通过定位服务警报开启定位后等待定位开启的主要内容,如果未能解决你的问题,请参考以下文章