Запрос разрешения местоположения, когда НЕ выполняется мониторинг в фоновом режиме?

Я использую Android Beacon Library. Начиная с Marshmallow, я вижу следующую ошибку, как ожидалось и задокументировано.

Отказ в разрешении: требуется разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION для получения результатов сканирования

У меня есть код ранжирования во фрагменте, и RuntimeException выдается, когда фрагмент отображается на экране, как и ожидалось, поскольку я не запрашиваю разрешение. Если я нажимаю кнопку «Домой», вызывается Pause, и я отключаю beaconManager, и исключение больше не генерируется, как и ожидалось. Возвращаясь к Activity из предыдущего списка приложений, исключение RuntimeException выдается снова при каждом сканировании.

Почему возникает исключение, когда на переднем плане, даже если я добавил разрешение в AndroidManifest?

Согласно документации ЗДЕСЬ, вам нужно только предложить пользователю разрешение местоположения, если вы выполняете сканирование в фоновом режиме?

вы получите следующую ошибку в LogCat, когда попытаетесь выполнить сканирование Bluetooth в фоновом режиме, и маяки не будут обнаружены

Означает ли это ТОЛЬКО фоновое сканирование, или я неверно истолковываю документацию, и вы все равно должны запрашивать? Я хочу избежать дополнительных (возможно, отталкивающих нервных пользователей) запроса разрешения внутри приложения, если этого можно избежать !!

Мой манифест содержит -

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

Мой фрагмент кода из фрагмента -

public class NearMeNowFragment extends Fragment implements BeaconConsumer {

//Beacon manager stuff
private BeaconManager beaconManager;

<SNIP>


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    beaconManager = BeaconManager.getInstanceForApplication(getActivity());
    beaconManager.getBeaconParsers().add(new BeaconParser().
            setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.near_me_now, container, false);

    //Set up beacon stuff if Bluetooth available
    if (verifyBluetooth(false)) {
        beaconManager.bind(this);
    }

    <SNIP>

    return rootView;
}


/***************************
Beacon config methods
****************************
*/

@Override
public void onBeaconServiceConnect() {
    //update all scan periods
    beaconManager.setForegroundScanPeriod(1100l);
    beaconManager.setForegroundBetweenScanPeriod(8900l);
    beaconManager.setAndroidLScanningDisabled(true);
    try {
        beaconManager.updateScanPeriods();
    } catch (RemoteException e) {
        e.printStackTrace();
    }

    beaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
            if (beacons.size() > 0) {
                <SNIP>
                //handling beacons here
                ...
            } else {
                Log.i(TAG, "ZERO BEACONS IN SCAN");
            }
        }
    });

    try {
        beaconManager.startRangingBeaconsInRegion(new Region(TAG, null, null, null));
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

@Override
public Context getApplicationContext() {
    return getActivity().getApplicationContext();
}

@Override
public void unbindService(ServiceConnection serviceConnection) {
    getActivity().unbindService(serviceConnection);
}

@Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int mode) {
    return getActivity().bindService(intent, serviceConnection, mode);
}


@Override
public void onPause() {
    super.onPause();

    if(beaconManager.isBound(this)){
        beaconManager.unbind(this);
    }
}

@Override
public void onResume() {
    super.onResume();

    beaconManager.bind(this);
}

@Override
public void onDestroy() {
    super.onDestroy();
    if(beaconManager.isBound(this)){
        beaconManager.unbind(this);
    }
}

}

Моя фактическая ошибка Logcat

W / Binder ﹕ Обнаружено исключение RuntimeException из реализации заглушки связующего. java.lang.SecurityException: требуется разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION для получения результатов сканирования


person WallyHale    schedule 15.10.2015    source источник


Ответы (2)


Чтобы уточнить, требования различаются в зависимости от того, установлен ли targetSdkVersion 23 в файле build.gradle.

Если вы настроили таргетинг на SDK 23 (Marshmallow) или выше:

  • Вы должны объявить android.permission.ACCESS_COARSE_LOCATION или android.permission.ACCESS_FINE_LOCATION в своем манифесте.
  • Вы должны запросить у пользователя разрешение, как описано в моем сообщении в блоге здесь.
  • Пользователь должен принять это разрешение и не отключать его.
  • Если любое из вышеперечисленных требований не выполняется, вы не сможете обнаруживать маяки на переднем или заднем плане.

Если вы настроили таргетинг на SDK 22 или более раннюю версию:

  • При желании вы можете объявить android.permission.ACCESS_COARSE_LOCATION или android.permission.ACCESS_FINE_LOCATION в своем манифесте.
  • Пользователь может включить или отключить разрешение, перейдя в настройки.
  • Если одно из разрешений не предоставлено, вы все равно сможете обнаруживать маяки на переднем плане, но не в фоновом режиме.

См. здесь и здесь для получения дополнительных сведений.

person davidgyoung    schedule 15.10.2015
comment
Превосходно! Теперь я использую подсказку и получаю разрешение. Я просто хотел избежать этого, если упускал что-то очевидное. Возможно, стоит обновить первый абзац документации requesting_permission, чтобы не включать маяки в фоновом режиме ИЛИ на переднем плане? - person WallyHale; 15.10.2015
comment
Я только что прочитал вывод в вашем сообщении в блоге, он противоречит тому, что вы сказали выше ?? ЦИТАТА. Если у вас есть приложение-маяк, которое должно работать только на переднем плане, никаких изменений не требуется. Если у вас есть приложение-маяк, которое должно работать в фоновом режиме, вам необходимо обновить его, чтобы запросить соответствующие разрешения на местоположение, как описано в первом разделе. Мое приложение работает только на переднем плане, верно ?? - person WallyHale; 15.10.2015
comment
Я не должен хорошо себя объяснять. :) Если я изменю оператор на «Если у вас есть существующее приложение-маяк, которое еще не нацелено на SDK 23 и должно работать только на переднем плане, никаких изменений не потребуется». устраняет ли это кажущееся противоречие? - person davidgyoung; 15.10.2015
comment
Да ... Я просто хотел прояснить ситуацию и, надеюсь, избежать того, чтобы кто-либо в будущем совершил ту же ошибку, что и я :) Решение было действительно очевидным, но моя интерпретация его привела меня вверх по садовой дорожке. Таким образом, любое сканирование в SDK 23 должно запрашивать разрешение во время выполнения. Точка, конец :) - person WallyHale; 15.10.2015
comment
@davidgyoung Я следил за вашим руководством, но когда я предоставляю доступ к местоположению на моем устройстве, он перестает сканировать маяки. - person Vikash Parajuli; 26.11.2015
comment
Пожалуйста, откройте новый вопрос, показывающий ваш вывод logcat и разрешения в настройках приложения. - person davidgyoung; 26.11.2015

У меня была такая же проблема с моим приложением, когда я тестировал его на устройстве Marshmallow. Чтобы не запрашивать у пользователя разрешение, я просто изменил targetSdkVersion на 22. compileSdkVersion может остаться на 23. После изменения build.gradle вам может потребоваться запустить Инструменты> Android> Синхронизировать проект с файлами Gradle. Если вы используете Eclipse, targetSdkVersion находится в файле манифеста.

person Andrew F.    schedule 05.04.2016
comment
Да, вы можете настроить SDK более низкого уровня, но это не решение для тех из нас, кто хочет быть на переднем крае. Чтобы оставаться в курсе последних версий / устройств, необходимо запросить доступ. - person WallyHale; 06.04.2016
comment
Я просто хочу предоставить возможность не запрашивать пользователя. Для некоторых приложений не требуется устанавливать последнюю версию SDK. Вы должны использовать свое суждение. - person Andrew F.; 09.04.2016