Включите службы определения местоположения, не переходя на страницу настроек

123

В отличие от традиционного подхода, предлагающего пользователю перейти на страницу настроек, включить службы определения местоположения и вернуться снова, я заметил более простой способ сделать то же самое в некоторых последних приложениях.

Ссылаясь на снимок экрана ниже, он предлагает пользователю диалоговое окно для включения служб определения местоположения одним щелчком мыши, и оно работает в этих приложениях.

Как я могу добиться того же?

введите описание изображения здесь

GAMA
источник
14
Могут ли отрицательные избиратели указать причину?
GAMA
4
Спасибо, что задали этот вопрос. Проголосовал за
Локеш Пандей 04
1
@GAMA Вот как работает stackoverflow! Людям не нужна причина, чтобы голосовать против. Такое враждебное и отличное сообщество одновременно!

Ответы:

150

Это диалоговое окно создается LocationSettingsRequest.Builder, доступным в сервисах Google Play.

Вам нужно добавить в свое приложение зависимость build.gradle:

compile 'com.google.android.gms:play-services-location:10.0.1'

Затем вы можете использовать этот минимальный пример:

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
Извините, но я не понял первых двух строк:You need to add a dependency to your app build.gradle: compile 'com.google.android.gms:play-services:8.1.0'
GAMA
Вы можете найти более подробную информацию о том, как настроить Google Play Service здесь
Маттиа Маэстрини
где находится build.gradle ?
GAMA
Внутри каталога модуля вашего приложения. Обычно имя каталогаapp
Маттиа Маэстрини
3
Настройки Апи теперь лишены.
Sagar Kacha
27

Следуйте инструкциям, указанным ниже

1) Создайте по LocationRequestсвоему желанию

LocationRequest mLocationRequest = LocationRequest.create()
           .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
           .setInterval(10 * 1000)
           .setFastestInterval(1 * 1000);

2) СоздайтеLocationSettingsRequest.Builder

LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder()
               .addLocationRequest(mLocationRequest);
settingsBuilder.setAlwaysShow(true);

3) Получить LocationSettingsResponse Taskиспользуя следующий код

Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(this)
              .checkLocationSettings(settingsBuilder.build());

Примечание: LocationServices.SettingsApi не рекомендуется использовать SettingsClientвместо.

4) Добавьте, OnCompleteListenerчтобы получить результат от Задачи. По Taskзавершении клиент может проверить настройки местоположения, посмотрев на код состояния LocationSettingsResponseобъекта.

result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
    @Override
    public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
    try {
        LocationSettingsResponse response = 
                          task.getResult(ApiException.class);
        } catch (ApiException ex) {
            switch (ex.getStatusCode()) {
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        ResolvableApiException resolvableApiException = 
                                 (ResolvableApiException) ex;
                            resolvableApiException
                                   .startResolutionForResult(MapsActivity.this, 
                                         LOCATION_SETTINGS_REQUEST);
                    } catch (IntentSender.SendIntentException e) {

                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:

                    break;
            }
        }
    }
});  

СЛУЧАЙ 1: LocationSettingsStatusCodes.RESOLUTION_REQUIRED Местоположение не включено, но мы можем попросить пользователя включить местоположение, предложив ему включить местоположение в диалоговом окне (позвонив startResolutionForResult).

Запрос настроек местоположения карты Google

СЛУЧАЙ 2:: LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE Настройки местоположения не подходят. Однако у нас нет возможности исправить настройки, поэтому мы не будем показывать диалог.

5) OnActivityResult мы можем получить действие пользователя в диалоговом окне настроек местоположения. RESULT_OK=> Пользователь включил Местоположение. RESULT_CANCELLED- Пользователь отклонил запрос на настройку местоположения.

РевантКришнаКумар В.
источник
11

Его работа похожа на карты Google

Добавить зависимость в файл build.gradle

compile 'com.google.android.gms:play-services:8.3.0'

этот или тот

compile 'com.google.android.gms:play-services-location:10.0.1'

введите описание изображения здесь

import android.content.Context;
import android.content.IntentSender;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
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;

import java.util.List;

public class LocationOnOff_Similar_To_Google_Maps extends AppCompatActivity {

    protected static final String TAG = "LocationOnOff";

    private GoogleApiClient googleApiClient;
    final static int REQUEST_LOCATION = 199;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setFinishOnTouchOutside(true);

        // Todo Location Already on  ... start
        final LocationManager manager = (LocationManager) LocationOnOff_Similar_To_Google_Maps.this.getSystemService(Context.LOCATION_SERVICE);
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
            finish();
        }
        // Todo Location Already on  ... end

        if(!hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)){
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
        }

        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
            Log.e("keshav","Gps already enabled");
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
            enableLoc();
        }else{
            Log.e("keshav","Gps already enabled");
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
        }
    }


    private boolean hasGPSDevice(Context context) {
        final LocationManager mgr = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);
        if (mgr == null)
            return false;
        final List<String> providers = mgr.getAllProviders();
        if (providers == null)
            return false;
        return providers.contains(LocationManager.GPS_PROVIDER);
    }

    private void enableLoc() {

        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(LocationOnOff_Similar_To_Google_Maps.this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(Bundle bundle) {

                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            googleApiClient.connect();
                        }
                    })
                    .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult connectionResult) {

                            Log.d("Location error","Location error " + connectionResult.getErrorCode());
                        }
                    }).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);

            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.RESOLUTION_REQUIRED:
                            try {
                                // Show the dialog by calling startResolutionForResult(),
                                // and check the result in onActivityResult().
                                status.startResolutionForResult(LocationOnOff_Similar_To_Google_Maps.this, REQUEST_LOCATION);

                                finish();
                            } catch (IntentSender.SendIntentException e) {
                                // Ignore the error.
                            }
                            break;
                    }
                }
            });
        }
    }

}
Кешав Гера
источник
2
НастройкиApi теперь деприминированы
Сагар Кача
2
SettingsApi устарела. Теперь используйте SettingsClient: developers.google.com/android/reference/com/google/android/gms/…
Rishabh Chandel
9
implementation 'com.google.android.gms:play-services-location:16.0.0'

Объявление переменной

private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private static final int REQUEST_CHECK_SETTINGS = 214;
private static final int REQUEST_ENABLE_GPS = 516;

Открыть диалог с использованием кода ниже

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();

mSettingsClient = LocationServices.getSettingsClient(YourActivity.this);

mSettingsClient
    .checkLocationSettings(mLocationSettingsRequest)
    .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            //Success Perform Task Here
        }
    })
    .addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            int statusCode = ((ApiException) e).getStatusCode();
            switch (statusCode) {
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        ResolvableApiException rae = (ResolvableApiException) e;
                        rae.startResolutionForResult(YourActivity.this, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException sie) {
                        Log.e("GPS","Unable to execute request.");
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    Log.e("GPS","Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
            }
        }
    })
    .addOnCanceledListener(new OnCanceledListener() {
        @Override
        public void onCanceled() {
            Log.e("GPS","checkLocationSettings -> onCanceled");
        }
    });

onActivityResult

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

    if (requestCode == REQUEST_CHECK_SETTINGS) {
        switch (resultCode) {
            case Activity.RESULT_OK:
                //Success Perform Task Here
                break;
            case Activity.RESULT_CANCELED:
                Log.e("GPS","User denied to access location");
                openGpsEnableSetting();
                break;
        }
    } else if (requestCode == REQUEST_ENABLE_GPS) {
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

        if (!isGpsEnabled) {
            openGpsEnableSetting();
        } else {
            navigateToUser();
        }
    }
}

private void openGpsEnableSetting() {
    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivityForResult(intent, REQUEST_ENABLE_GPS);
}   
Кетан Рамани
источник
Спасибо! Если вы используете этот код во фрагменте, см. Stackoverflow.com/a/39579124/2914140 : вместо rae.startResolutionForResult(activity, REQUEST_CHECK_SETTINGS)call startIntentSenderForResult(rae.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null), иначе onActivityResult()не будет вызван.
CoolMind
@CoolMind Спасибо, может быть полезно для тех, кому это нужно для фрагмента
Кетан Рамани
@CoolMind, можно ли startIntentSenderForResultв методе использовать что-то подобное openGpsEnableSetting()?
Aliton Oliveira,
@AlitonOliveira, не могли бы вы подробно описать? В коде openGpsEnableSetting()просто запускается диалог для включения настроек GPS. После его завершения onActivityResult()вызывается с помощью requestCode == REQUEST_ENABLE_GPS.
CoolMind
onActivityResult()вызывается из Activity, и мне было интересно, можно ли вернуть результат в Fragmentподобное startIntentSenderForResult.
Алитон Оливейра,
8

Спасибо Маттиа Маэстрини +1

Решение Xamarin:

using Android.Gms.Common.Apis;
using Android.Gms.Location;

public const int REQUEST_CHECK_SETTINGS = 0x1;

private void DisplayLocationSettingsRequest()
{
    var googleApiClient = new GoogleApiClient.Builder(this).AddApi(LocationServices.API).Build();
    googleApiClient.Connect();

    var locationRequest = LocationRequest.Create();
    locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
    locationRequest.SetInterval(10000);
    locationRequest.SetFastestInterval(10000 / 2);

    var builder = new LocationSettingsRequest.Builder().AddLocationRequest(locationRequest);
    builder.SetAlwaysShow(true);

    var result = LocationServices.SettingsApi.CheckLocationSettings(googleApiClient, builder.Build());
    result.SetResultCallback((LocationSettingsResult callback) =>
    {
        switch (callback.Status.StatusCode)
        {
            case LocationSettingsStatusCodes.Success:
                {
                    DoStuffWithLocation();
                    break;
                }
            case LocationSettingsStatusCodes.ResolutionRequired:
                {
                    try
                    {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        callback.Status.StartResolutionForResult(this, REQUEST_CHECK_SETTINGS);
                    }
                    catch (IntentSender.SendIntentException e)
                    {
                    }

                    break;
                }
            default:
                {
                    // If all else fails, take the user to the android location settings
                    StartActivity(new Intent(Android.Provider.Settings.ActionLocationSourceSettings));
                    break;
                }
        }
    });
}

protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
    switch (requestCode)
    {
        case REQUEST_CHECK_SETTINGS:
            {
                switch (resultCode)
                {
                    case Android.App.Result.Ok:
                        {
                            DoStuffWithLocation();
                            break;
                        }
                    case Android.App.Result.Canceled:
                        {
                            //No location
                            break;
                        }
                }
                break;
            }
    }
}

НОТА:

Это не будет работать с Huawei или другими устройствами, на которых не установлены службы Google.

пьер
источник
Это не работает!! Не могли бы вы поделиться полным кодом
Омкар
Я пытаюсь вызвать метод DisplayLocationSettingsRequest () из метода OnCreate в Android Activity. Но, к сожалению, я не могу просмотреть всплывающее окно с запросом на настройку местоположения, которое включает Местоположение. Не могли бы вы мне помочь?
Omkar
@Omkar вы установили Xamarin.GooglePlayServices.Location через Nuget? Вы включили две строки выше using android.Gms.Common.Apis; using Android.Gms.Location;? После звонка LocationServices.SettingsApi.CheckLocationSettingsвы получите обратный звонок внутри result.SetResultCallback(? Поставьте точку
Пьер
Да, я добавил все предпосылки. И я получил результат как Id = 1, Status = WaitingForActivation, Method = (null). Но это время ожидания бесконечно, так как долго ждали, а результата не получили.
Omkar
4

Android Marshmallow 6 поддерживает разрешение во время выполнения. Разрешения времени выполнения работают только на Marshmallow, а на pre-Marshmallow он все еще работает по-старому.

Вы можете узнать больше об этом в официальном видео разработчика Android:

https://www.youtube.com/watch?v=C8lUdPVSzDk

И запрос разрешения: http://developer.android.com/training/permissions/requesting.html

Sharj
источник
Доступен ли API Marshmallow для разработки?
GAMA
Значит ли это, что рабочий процесс, показанный на скриншоте, может быть достигнут только в Marshmallow и более поздних версиях?
GAMA
Да, как указано в документации, это уровень API 23, поэтому он будет работать только на Marshmallow и новее.
Шардж
любым способом добиться того же поведения в моем собственном диалоговом окне
Сришти Рой
4

Спасибо Маттиа Маэстрини за ответ, я хотел бы добавить, что используя

compile 'com.google.android.gms:play-services-location:8.1.0'

хватит. Это предотвращает включение в ваше приложение ненужных библиотек и помогает снизить количество методов.

Вуонг Фам
источник
2

Котлин Решение

Добавить build.gradle(Module:app)

implementation 'com.google.android.gms:play-services-location:17.0.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'

после этого создайте эту функцию

fun enablegps() {

    val mLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(2000)
        .setFastestInterval(1000)

    val settingsBuilder = LocationSettingsRequest.Builder()
        .addLocationRequest(mLocationRequest)
    settingsBuilder.setAlwaysShow(true)

    val result = LocationServices.getSettingsClient(this).checkLocationSettings(settingsBuilder.build())
    result.addOnCompleteListener { task ->

        //getting the status code from exception
        try {
            task.getResult(ApiException::class.java)
        } catch (ex: ApiException) {

            when (ex.statusCode) {

                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {

                    Toast.makeText(this,"GPS IS OFF",Toast.LENGTH_SHORT).show()

                    // Show the dialog by calling startResolutionForResult(), and check the result
                    // in onActivityResult().
                    val resolvableApiException = ex as ResolvableApiException
                    resolvableApiException.startResolutionForResult(this,REQUEST_CHECK_SETTINGS
                    )
                } catch (e: IntentSender.SendIntentException) {
                    Toast.makeText(this,"PendingIntent unable to execute request.",Toast.LENGTH_SHORT).show()

                }

                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {

                    Toast.makeText(
                        this,
                        "Something is wrong in your GPS",
                        Toast.LENGTH_SHORT
                    ).show()

                }


            }
        }



    }


}
Джимале Абди
источник
1

В недавнем обновлении Marshmallow, даже если параметр «Местоположение» включен, вашему приложению потребуется явно запрашивать разрешение. Рекомендуемый способ сделать это - показать раздел разрешений вашего приложения, в котором пользователь может переключать разрешения по мере необходимости. Фрагмент кода для этого выглядит следующим образом:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Location Permission");
        builder.setMessage("The app needs location permissions. Please grant this permission to continue using the features of the app.");
        builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);}
        });
        builder.setNegativeButton(android.R.string.no, null);
        builder.show();
    }
} else {
    // do programatically as show in the other answer 
}

И переопределите onRequestPermissionsResultметод, как показано ниже:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_COARSE_LOCATION: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "coarse location permission granted");
                } else {
                    Intent intent = new Intent();
                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                    intent.setData(uri);
                    startActivity(intent);
                }
            }
        }
    }

Другой подход заключается в том, что вы также можете использовать SettingsApi, чтобы узнать, какие провайдеры местоположения включены. Если ни один из них не включен, вы можете запросить диалоговое окно для изменения параметра из приложения.

Махендра Лия
источник
1

Самый простой способ, который я нашел во время своего исследования, - это создать класс Util для этого процесса запроса местоположения, а затем вызвать его, чтобы включить для нас GPS.

Пожалуйста, проверьте этот блог! Это рассказало всю историю.

Harpreet
источник