auh*_*aan 7 android android-location xamarin.android xamarin android-permissions
如何提示用户打开位置?
应用程序应该使用用户的当前位置过滤位置列表.如果用户关闭了位置服务,应用程序应提示用户要求打开位置.
例如Trip Advisor应用程序执行此操作:
(不确定我是否可以在这里发布其他应用程序截图,但如果我不应该这样做,请说出来.并为全尺寸图片道歉,试图让它们变小,但是不喜欢它......)
在第一张图片中,您可以看到我已关闭位置服务.打开Trip Advisor应用程序,然后点击" 立刻接近我"选项,我会看到第二张图片,我被要求打开位置服务.点击按钮后,会出现一个对话框,以便我可以允许或禁止打开位置服务.如果点击" 确定",则会在设备上启用 " 位置"服务,然后应用程序会使用该服务.
我怎样才能做到这一点?
假设您正在名为 LocationActivity 的活动中执行所有这些操作。为此,您需要实现一些回调。下面是带注释的代码,以便您可以轻松了解哪个方法执行什么操作以及何时调用。
请记住在应用程序清单文件中添加权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Run Code Online (Sandbox Code Playgroud)
活动代码:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在这里阅读官方文档
找到了我要的解决方案。
要求
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
}
Run Code Online (Sandbox Code Playgroud)
在此代码中,如果locationSettingsResult.Status.StatusCode
是LocationSettingsStatusCodes.ResolutionRequired
(6
),则可能意味着- 位置已关闭,尽管我发现一种情况是,当设备具有关闭选项时,该位置未返回值。打开和关闭后,它可以正常工作,可能是设备上的错误,还是没有。
归档时间: |
|
查看次数: |
22220 次 |
最近记录: |