android 6.0中无位置许可的信标扫描

android 6.0中无位置许可的信标扫描,android,bluetooth,ibeacon,beacon,android-ibeacon,Android,Bluetooth,Ibeacon,Beacon,Android Ibeacon,大家好,我正在开发基于beacon的android应用程序,它在低于android 6.0的环境下运行良好,只需要蓝牙许可即可。但安卓6.0及以上版本要求提供蓝牙和定位许可 为什么我们需要为Android 6.0中的扫描信标授予定位权限? 提前感谢 我实际上正在开发类似的东西,这也让我感到惊讶,因为从逻辑上讲,通过蓝牙/低能量扫描信标不需要位置许可。这实际上适用于Android 6.0之前的版本,但谷歌决定改变这一点 : 访问硬件标识符 为了向用户提供更好的数据保护,从本版本开始,Android

大家好,我正在开发基于beacon的android应用程序,它在低于android 6.0的环境下运行良好,只需要蓝牙许可即可。但安卓6.0及以上版本要求提供蓝牙和定位许可

为什么我们需要为Android 6.0中的扫描信标授予定位权限?


提前感谢

我实际上正在开发类似的东西,这也让我感到惊讶,因为从逻辑上讲,通过蓝牙/低能量扫描信标不需要位置许可。这实际上适用于Android 6.0之前的版本,但谷歌决定改变这一点

:

访问硬件标识符 为了向用户提供更好的数据保护,从本版本开始,Android将删除使用Wi-Fi和蓝牙API的应用程序对设备本地硬件标识符的编程访问。WifiInfo.getMacAddress()和BluetoothAdapter.getAddress()方法现在返回的常量值为02:00:00:00:00

要通过蓝牙和Wi-Fi扫描访问附近外部设备的硬件标识符,您的应用程序现在必须具有“访问\u精细\u位置”或“访问\u粗略\u位置”权限:

WifiManager.getScanResults()
BluetoothDevice.ACTION\u已找到
BluetoothLeScanner.startScan()

注意:当运行Android 6.0(API级别23)的设备启动后台Wi-Fi或蓝牙扫描时,外部设备可以看到该操作,因为该操作源自随机MAC地址

这并不意味着你必须打开GPS,而是
Bluetooh/节省电池的定位模式


我检查了我很久以前做过的代码,不,你只需要启用蓝牙。正如我在代码中看到的。请忽略postNotification方法,因为这不是必需的

private void initBluetooth() {
        // Check if device supports Bluetooth Low Energy.
        if (!beaconManager.hasBluetooth()) {
            //Toast.makeText(this, "Device does not have Bluetooth Low Energy", Toast.LENGTH_LONG).show();
            return;
        }

        // If Bluetooth is not enabled, let user enable it.
        if (!beaconManager.isBluetoothEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, Constant.REQUEST_ENABLE_BT);
        } else {
            Log.v(this.getClass(), "---> bluetooth already is enabled");
            startService(new Intent(this, EstimoteService.class));
        }
    }
//估计服务等级

public class EstimoteService extends Service implements BeaconManager.RangingListener, BeaconManager.MonitoringListener {
    private static final int NOTIFICATION_ID = 123;
    private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("regionId", null, null, null);
    private Beacon beaconFound;

    private NotificationManager notificationManager;
    private BeaconManager beaconManager;

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

        initResources();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        notificationManager.cancel(NOTIFICATION_ID);

        // Default values are 5s of scanning and 25s of waiting time to save CPU cycles.
        // In order for this demo to be more responsive and immediate we lower down those values.
        beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0);
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                try {
                    beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });


        return START_NOT_STICKY;
    }

    private void initResources() {
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        beaconManager = new BeaconManager(this);
        beaconManager.setRangingListener(this);
        beaconManager.setMonitoringListener(this);
    }

    @Override
    public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
        if (beaconFound == null) {
            // Get the first available beaconFound
            if (beacons.isEmpty())
                return;

            beaconFound = beacons.get(0);
            final Region beaconRegion = new Region("regionId", beaconFound.getProximityUUID(), beaconFound.getMajor(), beaconFound.getMinor());
            beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
                @Override
                public void onServiceReady() {
                    try {
                        beaconManager.startMonitoring(beaconRegion);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    @Override
    public void onEnteredRegion(Region region, List<Beacon> beacons) {
        postNotification("Entered region");
        System.out.println("---> enter region");
    }

    @Override
    public void onExitedRegion(Region region) {
        postNotification("Exited region");
        System.out.println("---> exit region");
    }

    private void postNotification(String msg) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setSmallIcon(R.drawable.beacon_gray).setContentTitle("XXX").setContentText(msg);
        notificationManager.notify(NOTIFICATION_ID, builder.build());
    }
}
公共类EstimoteService扩展服务实现BeaconManager.RangListener、BeaconManager.MonitoringListener{
私有静态最终整数通知_ID=123;
私有静态最终区域所有\u估计\u信标\u区域=新区域(“regionId”,null,null,null);
私人信标被混淆;
私人通知经理通知经理;
私人BeaconManager BeaconManager;
@凌驾
public void onCreate(){
super.onCreate();
initResources();
}
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
notificationManager.cancel(通知ID);
//默认值为5秒的扫描时间和25秒的等待时间,以节省CPU周期。
//为了让这个演示更具响应性和即时性,我们降低了这些值。
beaconManager.setBackgroundScanPeriod(时间单位为秒,单位为1,0);
connect(新的beaconManager.ServiceReadyCallback(){
@凌驾
服务日上的公共无效(){
试一试{
信标管理器。启动(所有预计信标区域);
}捕获(远程异常){
e、 printStackTrace();
}
}
});
返回开始时间不粘;
}
私有资源(){
notificationManager=(notificationManager)getSystemService(Context.NOTIFICATION\u服务);
beaconManager=新的beaconManager(此);
beaconManager.setRangingListener(this);
beaconManager.setMonitoringListener(this);
}
@凌驾
发现公共无效OnBeaconsDiscovery(区域、列表信标){
if(beacfound==null){
//获取第一个可用的beacfund
if(beacons.isEmpty())
返回;
beaconfund=beacons.get(0);
最终区域beaconRegion=新区域(“regionId”,beacFound.getProximityUID(),beacFound.getMajor(),beacFound.getMinor());
connect(新的beaconManager.ServiceReadyCallback(){
@凌驾
服务日上的公共无效(){
试一试{
beaconManager.startMonitoring(beaconRegion);
}捕获(远程异常){
e、 printStackTrace();
}
}
});
}
}
@凌驾
公共区域(区域、列表信标){
通知后(“输入区域”);
System.out.println(“-->输入区域”);
}
@凌驾
公共无效onExitedRegion(区域){
通知后(“退出区域”);
System.out.println(“-->退出区域”);
}
私有void postNotification(字符串msg){
NotificationCompat.Builder=新建NotificationCompat.Builder(此);
builder.setSmallIcon(R.drawable.beacon_gray).setContentTitle(“XXX”).setContentText(msg);
notificationManager.notify(NOTIFICATION_ID,builder.build());
}
}

kggoh-对于Android棉花糖,为什么我们需要为6.0提供定位许可?有解决方案吗?@BossRustler目前还没有。