要求用户打开位置

时间:2017-03-31 10:47:01

标签: android xamarin xamarin.android android-permissions android-location

如何提示用户启用位置

该应用程序应该使用用户的当前位置过滤位置列表。如果用户关闭位置服务,应用应提示用户要求启用位置

例如 Trip Advisor 应用程序执行此操作:

enter image description here enter image description here enter image description here enter image description here

不确定我是否可以在此发布其他应用截图,但如果我不应该这样做,请说出来。并为完整尺寸的图片道歉,试图让它们变小,但SO没有'我很喜欢......

在第一张图片中,您可以看到我已关闭位置服务。打开 Trip Advisor 应用程序,然后点击现在我附近选项后,我会看到第二张图片,我被要求转在位置服务。点击按钮后,会出现一个对话框,以便我可以允许或禁止位置服务打开。如果我点按确定位置服务<设备上的已启用,该应用就会消耗它。

我怎样才能做到这一点?

6 个答案:

答案 0 :(得分:6)

使用以下代码段启用设备设置屏幕。

   Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
   startActivity(intent);

否则使用设置API 进行权限对话

private void displayLocationSettingsRequest(Context context) {
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API).build();
    googleApiClient.connect();

LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);

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();
        switch (status.getStatusCode()) {
            case LocationSettingsStatusCodes.SUCCESS:
                Log.i(TAG, "All location settings are satisfied.");
                break;
            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ");

                try {
                    // Show the dialog by calling startResolutionForResult(), and check the result
                    // in onActivityResult().
                    status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException e) {
                    Log.i(TAG, "PendingIntent unable to execute request.");
                }
                break;
            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
                break;
        }
    }
});

答案 1 :(得分:5)

找到我要求的解决方案。

<强>要求

Nuget Xamarin.GooglePlayServices.Location

<强>代码

Int64
    interval = 1000 * 60 * 1,
    fastestInterval = 1000 * 50;

try {
    GoogleApiClient
        googleApiClient = new GoogleApiClient.Builder( this )
            .AddApi( LocationServices.API )
            .Build();

    googleApiClient.Connect();

    LocationRequest
        locationRequest = LocationRequest.Create()
            .SetPriority( LocationRequest.PriorityBalancedPowerAccuracy )
            .SetInterval( interval )
            .SetFastestInterval( fastestInterval );

    LocationSettingsRequest.Builder
        locationSettingsRequestBuilder = new LocationSettingsRequest.Builder()
            .AddLocationRequest( locationRequest );

    locationSettingsRequestBuilder.SetAlwaysShow( false );

    LocationSettingsResult
        locationSettingsResult = await LocationServices.SettingsApi.CheckLocationSettingsAsync(
            googleApiClient, locationSettingsRequestBuilder.Build() );

    if( locationSettingsResult.Status.StatusCode == LocationSettingsStatusCodes.ResolutionRequired ) {
        locationSettingsResult.Status.StartResolutionForResult( this, 0 );
    }
} catch( Exception exception ) {
    // Log exception
}

使用此代码,如果locationSettingsResult.Status.StatusCodeLocationSettingsStatusCodes.ResolutionRequired6),则可能意味着 - 位置已关闭,但我和#39;发现一种情况,当设备关闭该选项时,它没有返回该值。打开和关闭后,它有效,可能是设备上的错误,或不是。

答案 2 :(得分:2)

假设您在Activity名称LocationActivity中执行所有这些操作。您需要为此目的实现一些回调。下面是带注释的代码,因此您可以轻松了解哪个方法执行什么操作以及何时调用。

请记住在应用清单文件中添加权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

活动代码:

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v13.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;

public class LocationActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    // Unique tag for the error dialog fragment
    private static final String DIALOG_ERROR = "dialog_error";
    // Bool to track whether the app is already resolving an error
    private boolean mResolvingError = false;
    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 555;

    int ACCESS_FINE_LOCATION_CODE = 3310;
    int ACCESS_COARSE_LOCATION_CODE = 3410;
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Build Google API Client for Location related work
        buildGoogleApiClient();
    }


    // When user first come to this activity we try to connect Google services for location and map related work
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }


    // Google Api Client is connected
    @Override
    public void onConnected(Bundle bundle) {
        if (mGoogleApiClient.isConnected()) {
            //if connected successfully show user the settings dialog to enable location from settings services
            // If location services are enabled then get Location directly
            // Else show options for enable or disable location services
            settingsrequest();
        }
    }


    // This is the method that will be called if user has disabled the location services in the device settings
    // This will show a dialog asking user to enable location services or not
    // If user tap on "Yes" it will directly enable the services without taking user to the device settings
    // If user tap "No" it will just Finish the current Activity
    public void settingsrequest() {
        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(mGoogleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        if (mGoogleApiClient.isConnected()) {

                            // check if the device has OS Marshmellow or greater than
                            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
                                if (ActivityCompat.checkSelfPermission(LocationActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(LocationActivity.this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                                    ActivityCompat.requestPermissions(LocationActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_CODE);
                                } else {
                                    // get Location
                                }
                            } else {
                                // get Location
                            }

                        }
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // 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(LocationActivity.this, REQUEST_RESOLVE_ERROR);
                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the error.
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are not satisfied. However, we have no way to fix the
                        // settings so we won't show the dialog.
                        break;
                }
            }
        });
    }


    // This method is called only on devices having installed Android version >= M (Marshmellow)
    // This method is just to show the user options for allow or deny location services at runtime
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 3310: {

                if (grantResults.length > 0) {

                    for (int i = 0, len = permissions.length; i < len; i++) {

                        if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                            // Show the user a dialog why you need location
                        } else if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            // get Location
                        } else {
                            this.finish();
                        }
                    }
                }
                return;
            }
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_RESOLVE_ERROR) {
            mResolvingError = false;
            switch (resultCode) {
                case Activity.RESULT_OK:
                    // get location method
                    break;
                case Activity.RESULT_CANCELED:
                    this.finish();
                    break;
            }
        }
    }


    @Override
    public void onConnectionSuspended(int i) {
    }


    // When there is an error connecting Google Services
    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
            } catch (IntentSender.SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
        }
    }


    /* Creates a dialog for an error message */
    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getSupportFragmentManager(), "errordialog");
    }

    /* Called from ErrorDialogFragment when the dialog is dismissed. */
    public void onDialogDismissed() {
        mResolvingError = false;
    }

    /* A fragment to display an error dialog */
    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() {
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
            return GoogleApiAvailability.getInstance().getErrorDialog(
                    this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            ((LocationActivity) getActivity()).onDialogDismissed();
        }
    }


    // Connect Google Api Client if it is not connected already
    @Override
    protected void onStart() {
        super.onStart();
        if (mGoogleApiClient != null) {
            mGoogleApiClient.connect();
        }
    }

    // Stop the service when we are leaving this activity
    @Override
    protected void onStop() {
        super.onStop();
        if (mGoogleApiClient != null) {
            mGoogleApiClient.disconnect();
        }
    }

}

您可以阅读官方文档here

答案 3 :(得分:1)

使用以下代码段打开“设备设置”屏幕。

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);

其他用于权限对话框的设置API

GoogleApiClient googleApiClient = new GoogleApiClient.Builder(mContext).addApi(LocationServices.API).build();
    googleApiClient.connect();

LocationRequest lReq = LocationRequest.create();
lReq.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
lReq.setInterval(10000);
lReq.setFastestInterval(10000 / 2);

LocationSettingsRequest.Builder lBuilder = new LocationSettingsRequest.Builder().addLocationRequest(lReq);
lBuilder.setAlwaysShow(true);

PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, lBuilder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
    @Override
    public void onResult(LocationSettingsResult result) {
        final Status status = result.getStatus();
        switch (status.getStatusCode()) {
            case LocationSettingsStatusCodes.SUCCESS:
                break;
        }
    }
});

答案 4 :(得分:0)

您可以使用以下class将用户移至设置。首先检查位置是否可用,请致电showSettingAlert

AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

  // Setting Dialog Title
  alertDialog.setTitle("GPS is settings");

  // Setting Dialog Message
  alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

  // On pressing Settings button
  alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog,int which) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        mContext.startActivity(intent);
     }
  });

  // on pressing cancel button
  alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
     }
  });

  // Showing Alert Message
  alertDialog.show();
  // Setting Dialog Message
  alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

  // On pressing Settings button
  alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog,int which) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        mContext.startActivity(intent);
     }
  });

  // on pressing cancel button
  alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
     }
  });

  // Showing Alert Message
  alertDialog.show();

答案 5 :(得分:-1)

尝试

private void turnGPSOn(){
   String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

   if(!provider.contains("gps")){ //if gps is disabled
    final Intent poke = new Intent();
    poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); 
    poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
    poke.setData(Uri.parse("3")); 
    sendBroadcast(poke);
 }
}

private void turnGPSOff(){
   String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

   if(provider.contains("gps")){ //if gps is enabled
    final Intent poke = new Intent();
    poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
    poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
    poke.setData(Uri.parse("3")); 
    sendBroadcast(poke);
}
}

private boolean canToggleGPS() {
   PackageManager pacman = getPackageManager();
PackageInfo pacInfo = null;

   try {
    pacInfo = pacman.getPackageInfo("com.android.settings", PackageManager.GET_RECEIVERS);
   } catch (NameNotFoundException e) {
    return false; //package not found
   }

   if(pacInfo != null){
    for(ActivityInfo actInfo : pacInfo.receivers){
        //test if recevier is exported. if so, we can toggle GPS.
        if(actInfo.name.equals("com.android.settings.widget.SettingsAppWidgetProvider") && actInfo.exported){
            return true;
        }
    }
 }

 return false; //default
}