android 6.0 中无需位置许可的信标扫描
Beacon scanning without location permission in android 6.0
大家好,我正在开发基于 android 的 beacon 应用程序,它在 Android 6.0 以下工作正常,它只需要蓝牙许可。但是Android 6.0及以上版本要求提供蓝牙和位置权限。
为什么在Android6.0中扫描信标需要位置权限?
提前致谢!!!
我实际上正在开发类似的东西,这也让我感到惊讶,因为从逻辑上讲,您不需要位置许可即可通过蓝牙/低功耗扫描信标。这实际上适用于 Android 6.0 之前的版本 - 但 Google 决定改变它。
Access to Hardware Identifier
To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:
WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address
这并不意味着您必须打开 GPS,而是 Bluetooh / Battery Saving
的定位模式请看这里的图片
我检查了我很久以前做的代码,不,你只需要启用蓝牙。正如我在我的代码中看到的那样。请忽略 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));
}
}
//EstimoteServiceclass
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());
}
}
大家好,我正在开发基于 android 的 beacon 应用程序,它在 Android 6.0 以下工作正常,它只需要蓝牙许可。但是Android 6.0及以上版本要求提供蓝牙和位置权限。
为什么在Android6.0中扫描信标需要位置权限?
提前致谢!!!
我实际上正在开发类似的东西,这也让我感到惊讶,因为从逻辑上讲,您不需要位置许可即可通过蓝牙/低功耗扫描信标。这实际上适用于 Android 6.0 之前的版本 - 但 Google 决定改变它。
Access to Hardware Identifier To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions:
WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()Note: When a device running Android 6.0 (API level 23) initiates a background Wi-Fi or Bluetooth scan, the operation is visible to external devices as originating from a randomized MAC address
这并不意味着您必须打开 GPS,而是 Bluetooh / Battery Saving
的定位模式请看这里的图片
我检查了我很久以前做的代码,不,你只需要启用蓝牙。正如我在我的代码中看到的那样。请忽略 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));
}
}
//EstimoteServiceclass
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());
}
}