I am using this code for ranging and monitoring in Altbeacon
class Appclass extends Application implements BootstrapNotifier {
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
public static Region region1;
private static boolean activityVisible;
public static Appclass instances;
public static BeaconManager beaconManager;
public void onCreate() {
super.onCreate();
instances = this;beaconManager=org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(1100l);
beaconManager.setForegroundBetweenScanPeriod(0l);
beaconManager.setAndroidLScanningDisabled(true);
beaconManager.setBackgroundBetweenScanPeriod(01);
beaconManager.setBackgroundScanPeriod(1100l);
try {
beaconManager.updateScanPeriods();
} catch (Exception e) {
}
Log.d("", "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
region1 = new Region("backgroundRegion",
null, null, null);
regionBootstrap = new RegionBootstrap(this, region1);
backgroundPowerSaver = new BackgroundPowerSaver(this);
}
#Override
public void didEnterRegion(Region region) {
Log.d("ABC", "Enter");
Log.d("ABC value", region.getId2() + " " + region.getId3());
try { Intent i = new Intent(getApplicationContext(), AbcService.class);
startService(i);
} catch (Exception e) {
}
}
#Override
public void didExitRegion(Region region) {
Log.d("ABC", "exit");
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
and then in my AbcService class code is:
class AbcService extends Service implements BeaconConsumer, MonitorNotifier, RangeNotifier {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Appclass.beaconManager.bind(this);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
} catch (Exception e) {
}
return START_STICKY;
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
Log.d("ABC", "range");
}
#Override
public void onBeaconServiceConnect() {
Appclass.beaconManager.setMonitorNotifier(this);
Appclass.beaconManager.setRangeNotifier(this);
}
#Override
public void didEnterRegion(Region region) {
try {
Log.d("ABC", "didEnterRegion");
Log.d("ABC", "" + region.getId2() + region.getId3());
Appclass.beaconManager.startRangingBeaconsInRegion(Appclass.region1);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didExitRegion(Region region) {
try {
Log.d("ABC", "didExitRegion");
Appclass.beaconManager.stopRangingBeaconsInRegion(Appclass.region1);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
}
now issue are getting that the didEnterRegion method of Application class calling every time when we enter in beacon range but the didEnterRegion method of AbcService class not calling some time and also not start ranging. what is the issue in my code?
A few tips:
Start ranging the same time as you start monitoring. There is no reason to wait for an entered region callback or to stop ranging when you exit the region.
Add logging to didDetermineStateFirRegion. This method gets called when a beacon appears after app startup even if the device was already in region from when it was previously running. didEnterRegion only gets called if beacons matching the region actually disappear for 15+ seconds and then reappear.
Related
When I use other commercial beacon scanners, beacons are caught normally, but when I use this source code I made, they are not caught at all.
It is confirmed that the "didRangeBeaconsInRegion" function continues to work, but the number of beacons always returns 0. Please check what the problem is.
public class MainActivity extends AppCompatActivity implements BeaconConsumer {
TextView textView;
private BeaconManager beaconManager;
String beaconUUID="00000000000000000000000000000054"; // beacon -uuid
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private String TAG = "CHS_BEA";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=findViewById(R.id.tv_message);
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25\""));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
//beaconManager.setBackgroundMode(true);
beaconManager.bind(this);
}// onCreate()..
#Override
public void onBeaconServiceConnect() {
beaconManager.removeAllMonitorNotifiers();
Log.i(TAG, "onBeaconServiceConnect Start");
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
Log.i(TAG, "didRangeBeaconsInRegion Start -> " + region.toString());
Log.i(TAG, "didRangeBeaconsInRegion beacons -> " + beacons.size());
}
});
beaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
Log.i(TAG, "I just saw an beacon for the first time!");
Toast.makeText(MainActivity.this, "didEnterRegion - 비콘 연결됨", Toast.LENGTH_SHORT).show();
textView.setText("Beacon connected");
}
#Override
public void didExitRegion(Region region) {
Log.i(TAG, "I no longer see an beacon");
Toast.makeText(MainActivity.this, "didExitRegion - 비콘 연결 끊김", Toast.LENGTH_SHORT).show();
textView.setText("Beacon disconnected");
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
Log.i(TAG, "I have just switched from seeing/not seeing beacons: "+state);
}
});
try {
beaconManager.startMonitoringBeaconsInRegion(new Region("beacon",
null, null, null));
} catch (RemoteException e) { }
try
{
beaconManager.startRangingBeaconsInRegion(new Region("beacon",
null, null, null));
}
catch (RemoteException e)
{
}
}// onBeaconServiceConnect()..
#Override
public void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}// MainActivity class..``
I am using altbeacon for android and i cant't detect my beacon. I have tried https://github.com/AltBeacon/android-beacon-library-reference sample code also but can't detect beacon. Here is my code:
public class BeaconApplication extends Application implements BootstrapNotifier {
private Region region;
private RegionBootstrap regionBootstrap;
private BeaconManager beaconManager;
#Override
public void onCreate() {
super.onCreate();
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setBackgroundScanPeriod(5000);
beaconManager.setBackgroundBetweenScanPeriod(10000);
region = new Region("backgroundRegion",
Identifier.parse("EBEFD083-70A2-47C8-9837-E7B5634DF524"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
Log.i("selfBeacon", "Bootstrap created");
}
#Override
public void didEnterRegion(Region region) {
Log.i("selfBeacon", "Bootstrap didEnterRegion");
regionBootstrap.disable();
Intent intent = new Intent(this, SelfBeaconService.class);
if (Build.VERSION.SDK_INT >= 26) {
startForegroundService(intent);
} else {
startService(intent);
}
Log.i("selfBeacon", "Service start commanded");
}
#Override
public void didExitRegion(Region region) {
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
public void resumeScanning () {
beaconManager.setBackgroundScanPeriod(5000);
beaconManager.setBackgroundBetweenScanPeriod(10000);
regionBootstrap = new RegionBootstrap(this, region);
Log.i("selfBeacon", "scanning resumed");
}
}
public class SelfBeaconService extends Service implements BeaconConsumer {
private BeaconManager beaconManager;
private Region region;
private int noBeaconDetectedCount = 0;
#Override
public void onCreate() {
super.onCreate();
Log.i("selfBeaconService", "onCreate");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("selfBeaconService", "onStartCommand");
broadcastSystemLog("Beacon Service onCreate triggered.");
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.setEnableScheduledScanJobs(false); //Stop scanning
beaconManager.setForegroundScanPeriod(2000);
beaconManager.setForegroundBetweenScanPeriod(2000);
beaconManager.bind(this);
region = new Region("foreground region",
Identifier.parse("EBEFD083-70A2-47C8-9837-E7B5634DF524"), null, null);
startForeground();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onBeaconServiceConnect() {
Log.i("selfBeaconService", "onBeaconServiceConnect");
broadcastSystemLog("onBeaconServiceConnect triggered.");
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
if (collection.size() > 0) {
noBeaconDetectedCount = 0;
double closestDistance = -1;
for (Beacon each : collection) {
if (closestDistance == -1) {
closestDistance = each.getDistance();
} else if (each.getDistance() < closestDistance) {
closestDistance = each.getDistance();
}
}
Log.i("selfBeaconService", "didRangeBeaconsInRegion, the closest beacon is about " +
closestDistance + " meters away.");
broadcastToActivity("The closest beacon is about " +
closestDistance + " meters away.");
} else {
noBeaconDetectedCount++;
broadcastToActivity("No beacon has been detected for " + noBeaconDetectedCount + " times");
if (noBeaconDetectedCount > 10) { //10*(2000ms+2000ms) = 40 seconds
stopForeground(true);
terminate();
}
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
Log.i("selfBeacon", "onDestroy");
broadcastSystemLog("BeaconService onDestroy triggered.");
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void broadcastToActivity (String message) {
Intent intent = new Intent();
intent.setAction("beaconBroadcast");
intent.putExtra("beaconService", message);
sendBroadcast(intent);
}
private void broadcastSystemLog (String message) {
Intent intent = new Intent();
intent.setAction("beaconBroadcast");
intent.putExtra("beaconServiceLog", message);
sendBroadcast(intent);
}
private void startForeground () {
NotificationCompat.Builder notificationBuilder = null;
Notification notification = null;
if (Build.VERSION.SDK_INT >= 26) {
notificationBuilder = new NotificationCompat.Builder(this, "rangingService")
.setContentTitle("Active Scanning")
.setContentText("App is scanning for nearby beacons");
notification = notificationBuilder.build();
} else {
notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("Active Scanning")
.setContentText("App is scanning for nearby beacons");
notification = notificationBuilder.build();
}
startForeground(1234, notification);
}
private void terminate () {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
beaconManager.removeAllRangeNotifiers();
beaconManager.unbind(this);
beaconManager.setEnableScheduledScanJobs(true);
((BeaconApplication)getApplication()).resumeScanning();
stopSelf();
Log.i("selfBeaconService", "service stopped");
broadcastSystemLog("BeaconSevice stopped.");
}
}
A few things to check:
Ensure you have added code to dynamically request location permission at runtime. See here for how to do that.
After adding the above, make sure this permission has been properly obtained. Go to. Settings->Apps->{your app name}->Permissions to see
Make sure Bluetooth and Location are enabled on your phone.
If you have checked all of the above and it still does not work, try an off the shelf beacon detector like BeaconScope. If it does not detect, there may be a problem with either your phone hardware or your beacon hardware.
I am using AltBeacon Library. I want to scan beacon in 5 min and 1 sec like that. My code not scanning properly on first time and second time scanning properly. please help me?
//this is my fragment class
public class LocationIdFragment extends Fragment {
#Override
public void onStart() {
super.onStart();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().startService(intent);
}
#Override
public void onResume() {
super.onResume();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void onPause() {
super.onPause();
getActivity().getApplicationContext().unbindService(mConnection);
mBound = false;
}
#Override
public void onStop() {
super.onStop();
Intent intent = new Intent(getActivity(), SimpleService.class);
getActivity().getApplicationContext().stopService(intent);
}
}
//this is my service class
public class SimpleService extends Service implements BeaconConsumer {
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
#Override
public void onCreate() {
super.onCreate();
beaconManager = BeaconManager.getInstanceForApplication(getBaseContext());
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(1000);//this is not scanning properly
beaconManager.setBackgroundScanPeriod(1000);
beaconManager.setForegroundBetweenScanPeriod(301000);
beaconManager.setBackgroundBetweenScanPeriod(301000);
beaconManager.bind(SimpleService.this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
try {
// Unbind scan beacon progress
if (beaconManager != null) {
beaconManager.unbind(SimpleService.this);
beaconManager.stopRangingBeaconsInRegion(new Region("sBeacon", null, null, null));
}
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
#Override
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
beacon = beacons.iterator().next();
getMajor = beacon.getId2().toString();//here i'm getting data
getMinor = beacon.getId3().toString();
beaconID = getMajor + "-" + getMinor;
DateFormat df = new SimpleDateFormat("dd-MM-yyyy/hh:mm:ss.mmm");// i'm getting different time
String sDate = df.format(Calendar.getInstance().getTime());
String[] sDateTime = sDate.split("/");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("sBeacon", null, null, null));
Log.i(TAG, "*** startRangingBeaconsInRegion ***");
Logger.info(" LocationIdFragment : Start Ranging BeaconsInRegion ");
} catch (RemoteException e) {
Log.i(TAG, "RemoteException: " + e);
}
}
}
My code has now reached checkpoint 1 and 2. However, it is only detecting the beacon once. I want it to keep receiving the location of the beacon (distance) every five seconds. How can I implement this? Thanks again
public class RangingService extends Service implements BeaconConsumer {
private BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
Handler handler;
String b = "";
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
// Let it continue running until it is stopped.
Log.d("Service", "Started");
beaconManager.bind(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"));
handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.d("Checkpoint", "5 seconds have passed");
}
};
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
startJob();
Log.d("Checkpoint", "Job has started");
Thread.sleep(5285);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
//return START_STICKY;
}
public void startJob() {
Log.d("Checkpoint", "Starting job for realzies");
//onBeaconServiceConnect();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Service", "Ended");
beaconManager.unbind(this);
}
#Override
public void onBeaconServiceConnect() {
Log.d("Checkpoint3", "Checkpoint3");
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
Log.d("Checkpoint1", "Checkpoint1");
if (beacons.size() > 0) {
Log.d("Checkpoint2", "Checkpoint2");
//EditText editText = (EditText)RangingActivity.this.findViewById(R.id.rangingText);
Beacon firstBeacon = beacons.iterator().next();
String a = "The first beacon " + firstBeacon.toString() + " is about " + firstBeacon.getDistance() + " meters away. RSSI = " + firstBeacon.getRssi();
Log.d("Service", a);
//logToDisplay(a);
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
Log.d("Checkpoint4", "Checkpoint4");
} catch (RemoteException e) { }
}
}
I recommend you remove the Handler and the Thread as they seem unnecessary here.
I think all you need do is remove the Handler and the Thread, and run beaconManager.setForegroundScanPeriod as follows. Additionally, as best active you should probably bind the BeaconManager after setting all of its properties.
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(5285);
beaconManager.bind(this);
If I enter a region of a beacon with my Android device I like to show a notification. Thats well documented at Android SDK Quickstart
This is just working as long as the app is active. How do I get notifications when the app is closed?
I build a service by myself:
BeaconRangingService.java
public class BeaconRangingService extends Service {
private static final String TAG = BeaconRangingService.class.getSimpleName();
private BeaconManager beaconManager;
#Override
public void onCreate() {
super.onCreate();
beaconManager = BeaconManager.newInstance(getApplicationContext());
beaconManager.setMonitorPeriod(MonitorPeriod.MINIMAL);
beaconManager.setForceScanConfiguration(ForceScanConfiguration.DEFAULT);
beaconManager.registerMonitoringListener(new BeaconManager.MonitoringListener() {
#Override
public void onMonitorStart() {
Log.v(TAG, "start monitoring beacons");
}
#Override
public void onMonitorStop() {
Log.wtf(TAG, "stop monitoring beacons");
}
#Override
public void onBeaconsUpdated(Region region, List<Beacon> list) {
}
#Override
public void onBeaconAppeared(Region region, Beacon beacon) {
Toast.makeText(getApplicationContext(), "Beacon appeared\n BEACON ID: " + beacon.getBeaconUniqueId(), Toast.LENGTH_SHORT).show();
}
#Override
public void onRegionEntered(Region region) {
}
#Override
public void onRegionAbandoned(Region region) {
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "service started");
if (!beaconManager.isBluetoothEnabled()) {
Log.w(TAG, "bluetooth disabled, stop service");
stopSelf();
} else {
connect();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.v(TAG, "service destroyed");
beaconManager.stopMonitoring();
beaconManager.disconnect();
beaconManager = null;
super.onDestroy();
}
private void connectBeaconManager() {
try {
beaconManager.connect(new OnServiceBoundListener() {
#Override
public void onServiceBound() {
try {
HashSet<Region> regions = new HashSet<>();
regions.add(Region.EVERYWHERE);
beaconManager.startMonitoring(regions);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
}
}
AndroidManifest.xml
<service
android:name="com.your.package.BeaconRangingService"
android:exported="false"/>
start service
Intent intent = new Intent(this, BeaconRangingService.class);
startService(intent);
I know nothing regarding kontakt.io but there is a library and reference app for AltBeacon which provides this functionality. https://github.com/AltBeacon
I believe this is generic Android functionality, and not anything magic to their implementation.
#erdna have you tested the sample kontakt admin app? There is an approach in which Toasts appear when the application is in foreground and standard notifications appear when the app is working in background.
https://github.com/kontaktio/kontakt-beacon-admin-sample-app
#erdna I guess that it should be IntentService for long running services, that monitors incoming beacon events as intents in a onHandleIntent(Intent intent) method. #dawid-gdanski I'm not sure what class do you refer to.