1
votes

I have an android application. My purpose is detect Ibeacons with using AltBeacon library. I used Monitoring Example Code from AltBeacon Library Site Link: (http://altbeacon.github.io/android-beacon-library/samples.html). But I cannot detect any Ibeacon. And cannot get any log about detection of any beacon.

My Manifest File is like that:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ibeaconscanner.ibeaconproject.ibeaconproject" >

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

I added Requesting Permission codes to MainActivity.java to solve problem but couldn't. My MainActivity.java like that:

public class MainActivity extends Activity implements BeaconConsumer {
    protected static final String TAG = "MyApp";
    private BeaconManager beaconManager;
    private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("This app needs location acces");
                builder.setMessage("Please grat location acces so this app can detect beacons");
                builder.setPositiveButton(android.R.string.ok, null);
                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialogInterface) {
                        requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
                    }
                });
            }
        }

        setContentView(R.layout.activity_main);
        beaconManager = BeaconManager.getInstanceForApplication(this);
        beaconManager.bind(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        beaconManager.unbind(this);
    }

    @Override
    public void onBeaconServiceConnect() {
        beaconManager.setMonitorNotifier(new MonitorNotifier() {
            @Override
            public void didEnterRegion(Region region) {
                Log.d(TAG, "I just saw an beacon for the first time!");
            }

            @Override
            public void didExitRegion(Region region) {
                Log.d(TAG, "I no longer see an beacon");
            }

            @Override
            public void didDetermineStateForRegion(int state, Region region) {
                Log.d(TAG, "I have just switched from seeing/not seeing beacons: " + state);
            }
        });

        try {
            beaconManager.startMonitoringBeaconsInRegion(new Region("myMonitoringUniqueId", null, null, null));
        } catch (RemoteException e) {
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_COARSE_LOCATION: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "coarse location permission granted");
                } else {
                    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("Functionality limited");
                    builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
                    builder.setPositiveButton(android.R.string.ok, null);
                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                        @Override
                        public void onDismiss(DialogInterface dialogInterface) {

                        }
                    }
                    );
                    builder.show();
                }
                return;
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
2

2 Answers

0
votes

To detect iBeacons, you will need to modify the altbeacon library to make it understand the ibeacon packet format. Try this in onCreate function :

beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
                setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
        beaconManager.setForegroundScanPeriod(1000l);
        beaconManager.setForegroundBetweenScanPeriod(10000l);
        beaconManager.bind(this);
  1. setBeaconLayout defines the packet structure for detecting iBeacons. You can learn more about the packet structure here.

  2. setForegroundScanPeriod is set as 1 second and setForegroundBetweenScanPeriod is set as 10 seconds in my code. You can change this to any value you want. You may probably want to reduce setForegroundBetweenScanPeriod to say 3 seconds depending on your need. Basically, these two settings define that the device be in scan mode for 1 second, and repeat scanning every 10 seconds.

UPDATE

To display UUIDs of detected beacons, use the following :

@Override
public void onBeaconServiceConnect() {

        beaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
            if (beacons.size() > 0) {
                 for (Beacon beacon : beacons) {   
                      logToDisplay("Detected " + beacon.toString() + " with UUID " + beacon.getId1().toString() + " and Major ID " + beacon.getId2().toString() + " and Minor ID " + beacon.getId3().toString()); 
                }
            }
            else {
                logToDisplay("No iBeacons detected");
            }
        }

    });

    try {
        beaconManager.startRangingBeaconsInRegion(myRegion);
    } catch (RemoteException e) {   }

}

private void logToDisplay(final String line) {
    runOnUiThread(new Runnable() {
        public void run() {
            EditText editText = (EditText)RangingActivity.this.findViewById(R.id.rangingText);
            editText.append(line+"\n");
        }
    });
}
1
votes

A few tips:

  1. Make sure you can detect your beacon with an off-the-shelf beacon detection app like Locate. If you can't see the beacon, then there may be a hardware problem.

  2. By default, the library only detects beacons sending the AltBeacon format. If you are using a proprietary beacon type, you'll need to call beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("**PUT LAYOUT EXPRESSION HERE**")); to add the layout for your beacon type.

  3. If you are on Android 6, make sure that your app has granted location permissions. Go to Settings -> Apps -> [Your app name] -> Permissions, and make sure location permissions are granted.

  4. If you are on Android 6, check to see that Settings -> Location is set to On. This is necessary for some devices including the Nexus 5.

  5. If the above doesn't help, try adding logging to your app (like in onBeaconServiceConnect()) and report back which methods get called and which do not.