问题
I am using the AltBEacon Android library for developing an iBeacon app for Android devices. I am scanning for beacons, however, only two out of four beacons are found (sometimes 1/4).
I increasemBeaconManager.setForegroundScanPeriod(5000l);
to 5 seconds, but still same result. I am not sure if the CustomAdapter
I use for binding details to view is wrong or the issue is do with the mobile device (I am using Galaxy Note II - Android 4.4.2 (KitKat))? Can anyone locate my mistake?
Another issue is that the distance calculation from device to the beacon is returning not correct (when I am approximately 0.5 m away it returns betweem 3-6 m)
What am I doing wrong?
Note: I have checked UUID, Major, Minors of Beacon for any mistake. I have increased the scanning time. None of these worked.
Here is the Fragment that starts monitoring and ranging:
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);
}
}
And here is the custom adapter:
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");
}
}
}
回答1:
A few thoughts:
Try using an off-the-shelf beacon detection program like Locate, which uses the same Android Beacon Library under the hood. If the program detects your beacons reliably, then it is probably an issue in the custom code you mention.
Make sure your beacons are transmitting frequently enough. The baseline transmission frequency is 10 Hz, but the library with default settings will pick up beacons reliably that are transmitting at least 1 Hz. Increasing the
mBeaconManager.setForegroundScanPeriod();
as you describe should help this, but if the beacons are only transmitting at 0.1 Hz, then you would still have problems like you describe.Some Android devices have a combined Wi-Fi/Bluetooth chip that prevents reliable simultaneous operation of both these radios. Try disabling Wi-Fi and see if you get the same result.
回答2:
OK, I finally solved it. I ordered according to the beacon MAC address. So instead of:
public void initAll(Collection<Beacon> newBeacons) {
this.beacons.clear();
this.beacons.addAll(newBeacons);
}
I did:
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);
}
});
}
来源:https://stackoverflow.com/questions/27964761/all-beacons-are-not-shown-in-android-using-altbeacon-library