Android 融合位置更新

Posted

技术标签:

【中文标题】Android 融合位置更新【英文标题】:Android Fused Location Update 【发布时间】:2019-10-26 20:08:55 【问题描述】:

我正在开发一个 android 应用程序,我正在通过 Fused Location 获取设备当前位置。

我正在检查用户是否具有授予权限,如果是,我正在获取位置,但如果用户没有授予权限,我正在打开权限对话框并且用户单击允许,然后谷歌显示以下对话框:

我应该如何处理此对话框单击事件,因为如果用户单击“确定”但它没有获取设备位置或者我没有收到任何位置更新回调,会发生什么?我希望当用户单击“确定”时它应该获取位置。 我应该如何做到这一点?

【问题讨论】:

How to show enable location dialog like Google maps?的可能重复 位置设置弹窗会通过调用onActivityResult()给出回调结果,所以必须在activity中实现onActivityResult。例如参考 (developers.google.com/android/reference/com/google/android/gms/…)。 【参考方案1】:
     publi void myLocationButtonClicked()

GpsLocationTracker mGpsLocationTracker = new GpsLocationTracker(activity);
                if (mGpsLocationTracker.canGetLocation()) 

                    latitude = mGpsLocationTracker.getLatitude();
                    longitude = mGpsLocationTracker.getLongitude();

    if ((latitude != 0 && longitude != 0)
      else 
                        showLocationSnackBar(activity.getString(R.string.wait));
                    
                 else 
                    locationChecker();
                
      // this function to show dialog to open GPS if it is closed

     public void locationChecker() 


            LocationRequest mLocationRequest = LocationRequest.create();
            mLocationRequest.setInterval(10000);
            mLocationRequest.setFastestInterval(5000);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(mLocationRequest);

            SettingsClient client = LocationServices.getSettingsClient(activity);
            Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

            task.addOnSuccessListener(activity, locationSettingsResponse -> myLocationButtonClicked());

            task.addOnFailureListener(activity, e -> 
                if (e instanceof ResolvableApiException) 
                    // Location settings are not satisfied, but this can be fixed
                    // by showing the user a dialog.
                    try 
                        // Show the dialog by calling startResolutionForResult(),
                        // and check the result in onActivityResult().
                        ResolvableApiException resolvable = (ResolvableApiException) e;
                        resolvable.startResolutionForResult(activity,
                                REQUEST_GPS_RESULT_CODE_FOR_MAP_LOCATION);
                     catch (IntentSender.SendIntentException sendEx) 
                        // Ignore the error.
                    
                
            );
        

这是用于获取用户位置的GpsLocationTracker

public class GpsLocationTracker extends Service implements LocationListener 

    /**
     * min distance change to get location update
     */
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATE = 10;
    /**
     * min time for location update
     * 60000 = 1min
     */
    private static final long MIN_TIME_FOR_UPDATE = 60000;
    /**
     * context of calling class
     */
    private Context mContext;
    /**
     * flag for gps status
     */
    private boolean isGpsEnabled = false;
    /**
     * flag for network status
     */
    private boolean isNetworkEnabled = false;
    /**
     * flag for gps
     */
    private boolean canGetLocation = false;
    /**
     * location
     */
    private Location mLocation;
    /**
     * latitude
     */
    private double mLatitude;
    /**
     * longitude
     */
    private double mLongitude;
    /**
     * location manager
     */
    private LocationManager mLocationManager;


    /**
     * @param mContext constructor of the class
     */
    public GpsLocationTracker(Context mContext) 

        this.mContext = mContext;
        getLocation();
    


    /**
     * @return location
     */
    public Location getLocation() 

        try 

            mLocationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

            /*getting status of the gps*/
            isGpsEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            /*getting status of network provider*/
            isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGpsEnabled && !isNetworkEnabled) 

                /*no location provider enabled*/
             else 

                this.canGetLocation = true;

                /*getting location from network provider*/
                if (isNetworkEnabled) 

                    mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_FOR_UPDATE, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);

                    if (mLocationManager != null) 

                        mLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                        if (mLocation != null) 

                            mLatitude = mLocation.getLatitude();

                            mLongitude = mLocation.getLongitude();
                        
                    
                    /*if gps is enabled then get location using gps*/
                    if (isGpsEnabled) 

                        if (mLocation == null) 

                            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_FOR_UPDATE, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);

                            if (mLocationManager != null) 

                                mLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

                                if (mLocation != null) 

                                    mLatitude = mLocation.getLatitude();

                                    mLongitude = mLocation.getLongitude();
                                

                            
                        

                    
                
            

         catch (Exception e) 

            e.printStackTrace();
        

        return mLocation;
    

    /**
     * call this function to stop using gps in your application
     */
    public void stopUsingGps() 

        if (mLocationManager != null) 

            mLocationManager.removeUpdates(GpsLocationTracker.this);

        
    

    /**
     * @return latitude
     * <p/>
     * function to get latitude
     */
    public double getLatitude() 

        if (mLocation != null) 

            mLatitude = mLocation.getLatitude();
        
        return mLatitude;
    

    /**
     * @return longitude
     * function to get longitude
     */
    public double getLongitude() 

        if (mLocation != null) 

            mLongitude = mLocation.getLongitude();

        

        return mLongitude;
    

    /**
     * @return to check gps or wifi is enabled or not
     */
    public boolean canGetLocation() 

        return this.canGetLocation;
    

    /**
     * function to prompt user to open
     * settings to enable gps
     */
    public void showSettingsAlert() 

        AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(new ContextThemeWrapper(mContext, R.style.AppTheme));

        mAlertDialog.setTitle(R.string.gps_disabled);

        mAlertDialog.setMessage(R.string.enable_gps);

        mAlertDialog.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() 
            @Override
            public void onClick(DialogInterface dialog, int which) 
                Intent mIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(mIntent);
            
        );

        mAlertDialog.setNegativeButton(R.string.dialog_button_cancel, new DialogInterface.OnClickListener() 
            @Override
            public void onClick(DialogInterface dialog, int which) 
                dialog.cancel();

            
        );


        final AlertDialog mcreateDialog = mAlertDialog.create();
        mcreateDialog.show();
    

    @Override
    public IBinder onBind(Intent arg0) 
        // TODO Auto-generated method stub
        return null;
    

    public void onLocationChanged(Location location) 
        // TODO Auto-generated method stub

    

    public void onProviderDisabled(String provider) 
        // TODO Auto-generated method stub

    

    public void onProviderEnabled(String provider) 
        // TODO Auto-generated method stub

    

    public void onStatusChanged(String provider, int status, Bundle extras) 
        // TODO Auto-generated method stub

    




当用户点击确定按钮时,您必须检查onActivityResult() 中的结果。

 @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) 
            super.onActivityResult(requestCode, resultCode, data);

            if (requestCode == REQUEST_GPS_RESULT_CODE_FOR_MAP_LOCATION && resultCode == RESULT_OK)


myLocationButtonClicked();
        

【讨论】:

但是当@Harsh Shah 问问题时,确定按钮点击监听器在哪里......你能解释一下你的答案吗 我也在做同样的事情,但我没有收到任何 onActivityResult 回调 你是在活动还是片段? 我认为我们无法处理此对话框确定按钮单击,因为它在内部仅启用您的 GPS,但单击确定按钮后,您会获得一个状态代码,我正在共享答案,请在该代码中尝试这个如果 gsp 启用或未维护状态代码,我将处理状态代码让我分享... @HiteshKushwah 好的。等待您的答复【参考方案2】:

尝试此函数在按钮单击列表器上调用此函数并禁用您的 gps.. 当您单击按钮时,将出现 gps 对话框并启用 gps,当您再次单击按钮时,toast 将通过状态代码显示该句柄

    private void EnableGPSAutoMatically() 
        GoogleApiClient googleApiClient = null;
        if (googleApiClient == null) 
            googleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API).addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this).build();
            googleApiClient.connect();
            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(30 * 1000);
            locationRequest.setFastestInterval(5 * 1000);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

            // **************************
            builder.setAlwaysShow(true); // this is the key ingredient
            // **************************

            PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi
                    .checkLocationSettings(googleApiClient, builder.build());
            result.setResultCallback(new ResultCallback<LocationSettingsResult>() 
                @Override
                public void onResult(LocationSettingsResult result) 
                    final Status status = result.getStatus();
                    final LocationSettingsStates state = result
                            .getLocationSettingsStates();
                    switch (status.getStatusCode()) 
                        case LocationSettingsStatusCodes.SUCCESS:
                            toast("Success");

                            isgpson = true;
                            // All location settings are satisfied. The client can
                            // initialize location
                            // requests here.
                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
//                            toast("GPS is not on");
                            isgpson  = false;
                            // Location settings are not satisfied. But could be
                            // fixed by showing the user
                            // a dialog.
                            try 
                                // Show the dialog by calling
                                // startResolutionForResult(),
                                // and check the result in onActivityResult().
                                status.startResolutionForResult(Activity_Splash.this, 1000);

                             catch (IntentSender.SendIntentException e) 
                                // Ignore the error.
                            
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
//                            toast("Setting change not allowed");
                            // Location settings are not satisfied. However, we have
                            // no way to fix the
                            // settings so we won't show the dialog.
                            break;
                    
                
            );
        
    

【讨论】:

以上是关于Android 融合位置更新的主要内容,如果未能解决你的问题,请参考以下文章

融合的位置提供程序 setsmallestDisplacement 在 Android 中不起作用

无法使用融合位置API停止位置更新

在后台服务中使用融合位置获取GPS更新前(15分钟)?

Android服务不更新位置

融合位置提供程序 - 通过位移更新位置不起作用

Android 融合位置提供程序设置