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

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

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

У меня есть код ранжирования во фрагменте, и RuntimeException генерируется, когда фрагмент отображается на экране, как и ожидалось, поскольку я не запрашиваю разрешения. Если я нажимаю кнопку "Домой", вызывается "Пауза", и я отменяю привязку 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 из реализации заглушки Binder. java.lang.SecurityException: необходимо разрешение ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION для получения результатов сканирования

2 ответа

Решение

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

Если вы нацелены на SDK 23 (Зефир):

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

Если вы не выбираете SDK 23 ("Зефир"):

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

Смотрите здесь и здесь для более подробной информации.

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

Другие вопросы по тегам