通过定位服务警报开启定位后等待定位开启

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。

【讨论】:

以上是关于通过定位服务警报开启定位后等待定位开启的主要内容,如果未能解决你的问题,请参考以下文章

安卓手机怎么设置定位?

如何通过代码开启定位服务

想通过xcode开启定位服务

定位position介绍

怎样使用定位功能?百度地图、知道?

手机已开启定位,为什么微信上还是无法显示定位(以苹果手机为例)