【问题标题】:Prompting for location permission when NOT monitoring in background?不在后台监控时提示位置许可?
【发布时间】:2015-10-15 13:25:52
【问题描述】:

我正在使用 Android 信标库。从 Marshmallow 开始,我看到了以下错误,正如预期和记录的那样。

权限拒绝:需要 ACCESS_COARSE_LOCATION 或 ACCESS_FINE_LOCATION 权限才能获取扫描结果

我在 Fragment 中有测距代码,当 Fragment 出现在屏幕上时,会引发 RuntimeException,正如预期的那样,因为我没有提示许可。如果我点击主页按钮,则会调用暂停,并且我正在解除对 beaconManager 的绑定,并且不再像预期的那样再次抛出异常。从之前的应用列表返回到 Activity,每次扫描都会再次抛出 RuntimeException。

为什么我在AndroidManifest中添加了权限,但在前台还是抛出异常?

根据文档 HERE,后台扫描只需要提示用户位置权限吗?

当您尝试在后台进行蓝牙扫描时,您会在 LogCat 中收到以下错误,并且不会检测到任何信标

这是否意味着后台扫描,还是我误解了文档,无论如何您都必须提示?如果可以避免的话,我想避免在应用程序内出现额外的(可能会让紧张的用户感到反感)提示!

我的清单包含 -

<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 权限才能获取扫描结果

【问题讨论】:

    标签: android android-6.0-marshmallow ibeacon-android altbeacon


    【解决方案1】:

    澄清要求不同取决于您是否在 build.gradle 文件中设置targetSdkVersion 23

    如果您以 SDK 23(Marshmallow)或更高版本为目标:

    • 您必须在清单中声明 android.permission.ACCESS_COARSE_LOCATION 或 android.permission.ACCESS_FINE_LOCATION。
    • 您必须按照我的博文here. 中的说明提示用户获得许可
    • 用户必须接受此权限并且不能将其关闭。
    • 如果不满足上述任何要求,您将无法在前台或后台检测信标。

    如果您的目标是 SDK 22 或更低版本:

    • 您可以选择在清单中声明 android.permission.ACCESS_COARSE_LOCATION 或 android.permission.ACCESS_FINE_LOCATION。
    • 用户可以通过设置打开或关闭权限。
    • 如果未授予其中一项权限,您仍然可以在前台检测信标,但不能在后台检测。

    请参阅herehere 了解更多详情。

    【讨论】:

    • 太棒了!我现在正在使用提示并获得许可。如果我遗漏了一些明显的东西,我只是想避免这种情况。是否值得更新“requesting_permission”文档的第一段以在后台或前台不包含信标?
    • 我刚看了你博文的结论,和你上面说的矛盾??引用 - “如果您有一个只需要在前台工作的信标应用程序,则不需要进行任何更改。如果您有一个需要在后台工作的信标应用程序,您需要更新它以请求正确的位置权限,如中所述第一节。”。我的应用只在前台运行,对吗??
    • 我一定不能很好地解释自己。 :) 如果我将声明更改为“如果您有一个尚未针对 SDK 23 并且只需要在前台工作的现有信标应用程序,则无需进行任何更改。”这会让感知到的矛盾消失吗?
    • 是的 .. 我只是想澄清一下,希望以后避免任何人犯同样的错误:) 解决方案确实很明显,但我对它的解释让我走上了花园小路。因此,对 SDK 23 的任何扫描都必须在运行时提示许可。句号,结束:)
    • @davidgyoung 我按照您的教程进行操作,但是当我在我的设备上授予位置访问权限时,它会停止扫描信标。
    【解决方案2】:

    当我在 Marshmallow 设备上测试我的应用时,我遇到了同样的问题。为了避免提示用户许可,我只是将 targetSdkVersion 更改为 22。compileSdkVersion 可以保持在 23。更改 build.gradle 后,您可能需要运行 Tools > Android > Sync Project with Gradle Files。如果您使用 Eclipse,则 targetSdkVersion 在清单文件中。

    【讨论】:

    • 是的,您可以针对较低的 SDK,但对于我们这些想要处于最前沿的人来说,这不是一个解决方案。为了保持最新版本/设备的最新状态,有必要提示访问。
    • 我只是想提供一个选项来避免提示用户。某些应用程序不需要针对最新的 SDK。你必须运用你的判断力。
    猜你喜欢
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多