android 6.0中无位置许可的信标扫描
大家好,我正在开发基于beacon的android应用程序,它在低于android 6.0的环境下运行良好,只需要蓝牙许可即可。但安卓6.0及以上版本要求提供蓝牙和定位许可 为什么我们需要为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
提前感谢 我实际上正在开发类似的东西,这也让我感到惊讶,因为从逻辑上讲,通过蓝牙/低能量扫描信标不需要位置许可。这实际上适用于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目前还没有。