使用 altBeacon 库的 Android 中未显示所有信标
All beacons are not shown in Android using altBeacon library
我正在使用 AltBEacon Android library 为 Android 设备 开发 iBeacon 应用程序。我正在扫描信标,但是,只找到了四个信标中的两个(有时是 1/4)。
我将mBeaconManager.setForegroundScanPeriod(5000l);
增加到 5 秒,但结果仍然相同。我不确定我用于绑定详细信息以查看的 CustomAdapter
是否有误,或者问题出在移动设备上(我使用的是 Galaxy Note II - Android 4.4.2 (KitKat))? 谁能找出我的错误?
另一个问题是从设备到信标的距离计算返回不正确(当我距离它大约 0.5 米时,它 returns 在 3-6 米之间)
我做错了什么?
注:Beacon的UUID、Major、Minors我都检查过有没有错误。我增加了扫描时间。 None 其中有效。
这里是开始监听测距的Fragment:
public class FragmentScanBeacons extends Fragment implements BeaconConsumer{
public static Region mRegion = new Region("Server", Identifier.parse("Here is my UUID"), null, null);
private BeaconManager mBeaconManager;
private BeaconBaseAdapter beaconBaseAdapter;
private ListView beaconsListLv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBeaconManager = BeaconManager.getInstanceForApplication(getActivity());
//BEACON PARSER
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
//mBeaconManager.debug = true;
beaconBaseAdapter = new BeaconBaseAdapter(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_beacons, container, false);
//UI
beaconsListLv = (ListView) view.findViewById(R.id.beaconsListView);
//Set Adapter
beaconsListLv.setAdapter(beaconBaseAdapter);
//Check for bluetooth and Scan for Beacon
verifyBluetooth();
//Start Monitoring and Ranging
mBeaconManager.bind(this);
return view;
}
@Override
public void onResume() {
super.onResume();
if(mBeaconManager.isBound(this)){
mBeaconManager.setBackgroundMode(false);
}
}
@Override
public void onPause() {
super.onPause();
if(mBeaconManager.isBound(this)){
mBeaconManager.setBackgroundMode(true);
}
}
@Override
public void onDestroy() {
super.onDestroy();
mBeaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
try {
//Scan lasts for SCAN_PERIOD time
mBeaconManager.setForegroundScanPeriod(1000l);
//mBeaconManager.setBackgroundScanPeriod(0l);
//Wait every SCAN_PERIOD_INBETWEEN time
mBeaconManager.setForegroundBetweenScanPeriod(0l);
//Update default time with the new one
mBeaconManager.updateScanPeriods();
}
catch (RemoteException e){
e.printStackTrace();
}
//Set Monitoring
mBeaconManager.setMonitorNotifier(new MonitorNotifier() {
@Override
public void didEnterRegion(Region region) {
Log.d("TEST", "ENTERED beacon region");
//Start Raning as soon as you detect a beacon
try {
mBeaconManager.startRangingBeaconsInRegion(mRegion);
}
catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void didExitRegion(Region region) {
Log.d("TEST", "EXITED beacon region");
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
Log.d("TEST", "SWITCHED from seeing/not seeing beacon to state " + state);
}
});
//Set Ranging
mBeaconManager.setRangeNotifier(new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(final Collection<Beacon> beacons, Region region) {
if (beacons != null && beacons.size() > 0) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
beaconBaseAdapter.initAll(beacons);
}
});
}
}
});
try {
//Start Monitoring
mBeaconManager.startMonitoringBeaconsInRegion(mRegion);
}
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);
}
}
这里是自定义适配器:
public class BeaconBaseAdapter extends BaseAdapter {
private Context myContext;
private LayoutInflater inflater;
public static ArrayList<Beacon> beacons;
public BeaconBaseAdapter(Context context) {
this.myContext = context;
this.inflater = LayoutInflater.from(context);
this.beacons = new ArrayList<Beacon>();
}
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
notifyDataSetChanged();
}
@Override
public int getCount() {
return beacons.size();
}
@Override
public Beacon getItem(int position) {
return beacons.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.beacon_list_row, null);
convertView.setTag(new ViewHolder(convertView));
}
bind(getItem(position), position, convertView);
return convertView;
}
private void bind(Beacon beacon, int position, View view) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.manufacturerTextView.setText("Manufacturer: " + beacon.getManufacturer());
holder.idOneTextView.setText("UUID: " + beacon.getId1());
holder.idTwoTextView.setText("Major: " + beacon.getId2());
holder.idThreeTextView.setText("Minor: " + beacon.getId3());
holder.txPowerTextView.setText("TX-Power: " + beacon.getTxPower());
holder.rssiTextView.setText("RSSI: " + beacon.getRssi());
holder.distanceTextView.setText(String.format("DISTANCE: (%.2f m)", beacon.getDistance()));
holder.nameTextView.setText("Bluetooth Name: " + beacon.getBluetoothName());
holder.addressTextView.setText("Bluetooth Adrs: " + beacon.getBluetoothAddress());
}
static class ViewHolder {
final TextView nameTextView;
final TextView manufacturerTextView;
final TextView idOneTextView;
final TextView idTwoTextView;
final TextView idThreeTextView;
final TextView txPowerTextView;
final TextView rssiTextView;
final TextView distanceTextView;
final TextView addressTextView;
ViewHolder(View view) {
nameTextView = (TextView) view.findViewWithTag("name");
manufacturerTextView = (TextView) view.findViewWithTag("manufacturer");
idOneTextView = (TextView) view.findViewWithTag("id_one");
idTwoTextView = (TextView) view.findViewWithTag("id_two");
idThreeTextView = (TextView) view.findViewWithTag("id_three");
txPowerTextView = (TextView) view.findViewWithTag("tx_power");
rssiTextView = (TextView) view.findViewWithTag("rssi");
distanceTextView = (TextView) view.findViewWithTag("distance");
addressTextView = (TextView) view.findViewWithTag("address");
}
}
}
一些想法:
尝试使用现成的信标检测程序,例如 Locate,它在后台使用相同的 Android 信标库。如果程序可靠地检测到您的信标,则可能是您提到的自定义代码中的问题。
确保您的信标传输频率足够高。基线传输频率为 10 赫兹,但具有默认设置的库将可靠地拾取传输频率至少为 1 赫兹的信标。按照您的描述增加 mBeaconManager.setForegroundScanPeriod();
应该会有所帮助,但是如果信标仅以 0.1 Hz 的频率传输,那么您仍然会遇到您描述的问题。
一些 Android 设备有一个组合的 Wi-Fi/Bluetooth 芯片,可以防止这两种无线电同时可靠运行。尝试禁用 Wi-Fi,看看是否会得到相同的结果。
好的,我终于解决了。我是按照航标MAC address点的。所以代替:
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
}
我做到了:
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
//Sort
Collections.sort(this.beacons, new Comparator<Beacon>() {
@Override
public int compare(Beacon b1, Beacon b2) {
String mac1 = b1.getBluetoothAddress();
String mac2 = b2.getBluetoothAddress();
return mac1.compareTo(mac2);
}
});
}
我正在使用 AltBEacon Android library 为 Android 设备 开发 iBeacon 应用程序。我正在扫描信标,但是,只找到了四个信标中的两个(有时是 1/4)。
我将mBeaconManager.setForegroundScanPeriod(5000l);
增加到 5 秒,但结果仍然相同。我不确定我用于绑定详细信息以查看的 CustomAdapter
是否有误,或者问题出在移动设备上(我使用的是 Galaxy Note II - Android 4.4.2 (KitKat))? 谁能找出我的错误?
另一个问题是从设备到信标的距离计算返回不正确(当我距离它大约 0.5 米时,它 returns 在 3-6 米之间)
我做错了什么?
注:Beacon的UUID、Major、Minors我都检查过有没有错误。我增加了扫描时间。 None 其中有效。
这里是开始监听测距的Fragment:
public class FragmentScanBeacons extends Fragment implements BeaconConsumer{
public static Region mRegion = new Region("Server", Identifier.parse("Here is my UUID"), null, null);
private BeaconManager mBeaconManager;
private BeaconBaseAdapter beaconBaseAdapter;
private ListView beaconsListLv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBeaconManager = BeaconManager.getInstanceForApplication(getActivity());
//BEACON PARSER
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
//mBeaconManager.debug = true;
beaconBaseAdapter = new BeaconBaseAdapter(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_beacons, container, false);
//UI
beaconsListLv = (ListView) view.findViewById(R.id.beaconsListView);
//Set Adapter
beaconsListLv.setAdapter(beaconBaseAdapter);
//Check for bluetooth and Scan for Beacon
verifyBluetooth();
//Start Monitoring and Ranging
mBeaconManager.bind(this);
return view;
}
@Override
public void onResume() {
super.onResume();
if(mBeaconManager.isBound(this)){
mBeaconManager.setBackgroundMode(false);
}
}
@Override
public void onPause() {
super.onPause();
if(mBeaconManager.isBound(this)){
mBeaconManager.setBackgroundMode(true);
}
}
@Override
public void onDestroy() {
super.onDestroy();
mBeaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
try {
//Scan lasts for SCAN_PERIOD time
mBeaconManager.setForegroundScanPeriod(1000l);
//mBeaconManager.setBackgroundScanPeriod(0l);
//Wait every SCAN_PERIOD_INBETWEEN time
mBeaconManager.setForegroundBetweenScanPeriod(0l);
//Update default time with the new one
mBeaconManager.updateScanPeriods();
}
catch (RemoteException e){
e.printStackTrace();
}
//Set Monitoring
mBeaconManager.setMonitorNotifier(new MonitorNotifier() {
@Override
public void didEnterRegion(Region region) {
Log.d("TEST", "ENTERED beacon region");
//Start Raning as soon as you detect a beacon
try {
mBeaconManager.startRangingBeaconsInRegion(mRegion);
}
catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void didExitRegion(Region region) {
Log.d("TEST", "EXITED beacon region");
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
Log.d("TEST", "SWITCHED from seeing/not seeing beacon to state " + state);
}
});
//Set Ranging
mBeaconManager.setRangeNotifier(new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(final Collection<Beacon> beacons, Region region) {
if (beacons != null && beacons.size() > 0) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
beaconBaseAdapter.initAll(beacons);
}
});
}
}
});
try {
//Start Monitoring
mBeaconManager.startMonitoringBeaconsInRegion(mRegion);
}
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);
}
}
这里是自定义适配器:
public class BeaconBaseAdapter extends BaseAdapter {
private Context myContext;
private LayoutInflater inflater;
public static ArrayList<Beacon> beacons;
public BeaconBaseAdapter(Context context) {
this.myContext = context;
this.inflater = LayoutInflater.from(context);
this.beacons = new ArrayList<Beacon>();
}
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
notifyDataSetChanged();
}
@Override
public int getCount() {
return beacons.size();
}
@Override
public Beacon getItem(int position) {
return beacons.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.beacon_list_row, null);
convertView.setTag(new ViewHolder(convertView));
}
bind(getItem(position), position, convertView);
return convertView;
}
private void bind(Beacon beacon, int position, View view) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.manufacturerTextView.setText("Manufacturer: " + beacon.getManufacturer());
holder.idOneTextView.setText("UUID: " + beacon.getId1());
holder.idTwoTextView.setText("Major: " + beacon.getId2());
holder.idThreeTextView.setText("Minor: " + beacon.getId3());
holder.txPowerTextView.setText("TX-Power: " + beacon.getTxPower());
holder.rssiTextView.setText("RSSI: " + beacon.getRssi());
holder.distanceTextView.setText(String.format("DISTANCE: (%.2f m)", beacon.getDistance()));
holder.nameTextView.setText("Bluetooth Name: " + beacon.getBluetoothName());
holder.addressTextView.setText("Bluetooth Adrs: " + beacon.getBluetoothAddress());
}
static class ViewHolder {
final TextView nameTextView;
final TextView manufacturerTextView;
final TextView idOneTextView;
final TextView idTwoTextView;
final TextView idThreeTextView;
final TextView txPowerTextView;
final TextView rssiTextView;
final TextView distanceTextView;
final TextView addressTextView;
ViewHolder(View view) {
nameTextView = (TextView) view.findViewWithTag("name");
manufacturerTextView = (TextView) view.findViewWithTag("manufacturer");
idOneTextView = (TextView) view.findViewWithTag("id_one");
idTwoTextView = (TextView) view.findViewWithTag("id_two");
idThreeTextView = (TextView) view.findViewWithTag("id_three");
txPowerTextView = (TextView) view.findViewWithTag("tx_power");
rssiTextView = (TextView) view.findViewWithTag("rssi");
distanceTextView = (TextView) view.findViewWithTag("distance");
addressTextView = (TextView) view.findViewWithTag("address");
}
}
}
一些想法:
尝试使用现成的信标检测程序,例如 Locate,它在后台使用相同的 Android 信标库。如果程序可靠地检测到您的信标,则可能是您提到的自定义代码中的问题。
确保您的信标传输频率足够高。基线传输频率为 10 赫兹,但具有默认设置的库将可靠地拾取传输频率至少为 1 赫兹的信标。按照您的描述增加
mBeaconManager.setForegroundScanPeriod();
应该会有所帮助,但是如果信标仅以 0.1 Hz 的频率传输,那么您仍然会遇到您描述的问题。一些 Android 设备有一个组合的 Wi-Fi/Bluetooth 芯片,可以防止这两种无线电同时可靠运行。尝试禁用 Wi-Fi,看看是否会得到相同的结果。
好的,我终于解决了。我是按照航标MAC address点的。所以代替:
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
}
我做到了:
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
//Sort
Collections.sort(this.beacons, new Comparator<Beacon>() {
@Override
public int compare(Beacon b1, Beacon b2) {
String mac1 = b1.getBluetoothAddress();
String mac2 = b2.getBluetoothAddress();
return mac1.compareTo(mac2);
}
});
}