Comments (8)
If the onRegionEntered
and onRegionAbandoned
are called multiple times then I assume you configure BeaconManager
to search within more than one Region. If not then this is a bug. And you are correct, onRegionEntered
should be called exactly once at the very beginning once the Android device finds the BLE remote device. onRegionAbandoned
should be called after active monitor period when Android device has not detected any remote device transmitting the signal with parameters matching the specified region's parameters. Could you please provide configuration part of the BeaconManager
with all the details? How many regions do you specify?
from kontakt-android-sdk.
Thanks dawiddgdanski for your quick response.
I am posting my Android service code for which I am facing an issue:
import java.util.List;
import java.util.Timer;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.Vibrator;
import com.kontakt.sdk.android.configuration.ForceScanConfiguration;
import com.kontakt.sdk.android.configuration.MonitorPeriod;
import com.kontakt.sdk.android.connection.OnServiceBoundListener;
import com.kontakt.sdk.android.device.BeaconDevice;
import com.kontakt.sdk.android.device.Region;
import com.kontakt.sdk.android.factory.AdvertisingPackage;
import com.kontakt.sdk.android.factory.Filters;
import com.kontakt.sdk.android.manager.BeaconManager;
public class UpdateService extends Service{
Context ctx;
private BluetoothAdapter mBluetoothAdapter;
private BeaconManager beaconManager;
Timer timer;
private static final int NOTIFY_ME_ID=1337;
@Override
public void onCreate() {
super.onCreate();
ctx = getApplicationContext();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
System.out.println("we are here in update service");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onCreate();
beaconManager = BeaconManager.newInstance(ctx);
beaconManager.setMonitorPeriod(new MonitorPeriod(5000, 5000));
beaconManager.setForceScanConfiguration(ForceScanConfiguration.DEFAULT);
beaconManager.addFilter(Filters.newMajorFilter(31946));
beaconManager.addFilter(Filters.newMajorFilter(38560));
beaconManager.addFilter(new Filters.CustomFilter() { //create your customized filter
public boolean filter(AdvertisingPackage advertisingPackage) {
return advertisingPackage.getAccuracy() < 2; //accept beacons from distance 5m at most
}
@Override
public Boolean apply(AdvertisingPackage advertisingPackage) {
return advertisingPackage.getAccuracy() < 2;
}
});
beaconManager
.registerMonitoringListener(new BeaconManager.MonitoringListener() {
@Override
public void onMonitorStart() {
System.out.println("monitored start roster");
}
@Override
public void onMonitorStop() {
System.out.println("monitored stop");
}
@Override
public void onRegionEntered(final Region region) {
System.out.println("region entered");
showNotifitcation("New val");
}
@Override
public void onRegionAbandoned(final Region region) {
System.out.println("region abandoned");
}
@Override
public void onBeaconAppeared(Region arg0, BeaconDevice arg1) {
System.out.println("arg1 major"+arg1.getMajor());
System.out.println("arg1 major"+arg1.getUniqueId());
}
@Override
public void onBeaconsUpdated(Region arg0, List<BeaconDevice> arg1) {
System.out.println("beacon updated"+arg1.get(0).getMajor());
}
});
if(!beaconManager.isBluetoothEnabled()) {
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
} else if(beaconManager.isConnected()) {
startMonitoring();
} else {
connect();
}
return START_STICKY;
}
private void startMonitoring() {
try {
System.out.println("monitoring");
beaconManager.startMonitoring(); // starts monitoring everywhere
} catch (RemoteException e) {
}
}
private void connect() {
try {
System.out.println("monitor connecting");
beaconManager.connect(new OnServiceBoundListener() {
@Override
public void onServiceBound() {
try {
beaconManager.startMonitoring();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("on destroy");
beaconManager.stopMonitoring();
beaconManager.disconnect();
beaconManager = null;
}
public void showNotifitcation(String notify){
final NotificationManager mgr=
(NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification note=new Notification(R.drawable.schoolbus,
notify,
System.currentTimeMillis());
// This pending intent will open after notification click
PendingIntent i=PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class),
0);
note.setLatestEventInfo(this, notify,
"Click to see the value", i);
Vibrator v = (Vibrator)getApplicationContext()
.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
//After uncomment this line you will see number of notification arrived
//note.number=2;
mgr.notify(NOTIFY_ME_ID, note);
}
}
from kontakt-android-sdk.
- You specify Monitor Period with 5s of active scan duration and 5s of passive scan duration.
- You are interested only in 2 specific major values and accept devices to be seen from ~ 2 meters distance.
This is why onRegionEntered()
and onRegionAbandoned()
are called so often because if you move . But there are several issues that are implemented incorrectly.
You don't bind with the service, you rather rely on starting service via startService()
, aren't you?
@Override public IBinder onBind(Intent intent) { return null; }
If you rely on starting service then onStartCommand()
is called each time when start request is received.
In onStartCommand()
you reinstantiate BeaconManager
every time and the only reference to it is lost. Practically, with every startService()
request you create new BeaconManager
instance.
Services, by their nature are singletons (http://stackoverflow.com/questions/2518238/does-startservice-create-a-new-service-instance-or-using-the-existing-one).
Eventually, in the case you've posted creating BeaconManager multiple times does is not harmful as the BeaconManager binds to the same BeaconService instance but this is not the expected behaviour, is it?
I suggest moving instantiation/configuration of the BeaconManager to the UpdateService's `onCreate()' method so that it is instantiated exactly once (http://developer.android.com/reference/android/app/Service.html#onCreate()).
Secondly, in onStartCommand()
handle the logic with launching monitoring or checking whether the bluetooth is turned on or not.
Furthermore, please be aware that Bluetooth itself is quite battery-consuming. Consider, whether scanning remote devices during entire UpdateService's existence is the expected behaviour and whether the attempt to control it somehow could improve your app and battery life.
Remember, battery consumption goes inversely with UX.
Hope, that helps somehow.
Btw. here is some advice worth watching straight from Google Developers:
https://www.youtube.com/watch?v=VzYkVL1n4M8&list=PL1CrI7jw_egMwictLl6CAtgTKwTkV7p18
from kontakt-android-sdk.
Hey @mittalprayag25 what's the status of this issue?
from kontakt-android-sdk.
Hey Dawid,
Its going tough for me as of now, trying your way of doing. What exactly I
am trying to do is to detect the beacon from short range (Proximity
Immediate). But issue I am facing is when I am in range its calling
onRegionAbandoned and onRegionAppeared and onRegionEntered again and again.
I am using startService because I have to run it at the background for
infinite time and using start_sticky.
Below is my updated code as sugested by you. I am not understanding by its
calling callbacks again and again.
public class UpdateService extends Service{
Context ctx;
private BluetoothAdapter mBluetoothAdapter;
private BeaconManager beaconManager;
Timer timer;
private static final int NOTIFY_ME_ID=1337;
@OverRide
public void onCreate() {
super.onCreate();
ctx = getApplicationContext();
beaconManager = BeaconManager.newInstance(ctx);
beaconManager.addFilter(Filters.newMajorFilter(63854));
beaconManager.addFilter(Filters.newMajorFilter(14096));
beaconManager.setScanMode(BeaconManager.SCAN_MODE_BALANCED);
beaconManager.setBeaconActivityCheckConfiguration(BeaconActivityCheckConfiguration.DEFAULT);
beaconManager.setMonitorPeriod(MonitorPeriod.MINIMAL);
}
@OverRide
public IBinder onBind(Intent intent) {
return null;
}
@OverRide
public int onStartCommand(Intent intent, int flags, int startId) {
super.onCreate();
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
System.out.println("we are here");
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "Bluetooth BLE not supported", Toast.LENGTH_SHORT)
.show();
this.stopSelf();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a
// reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager = (BluetoothManager)
getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth not supported",
Toast.LENGTH_SHORT).show();
this.stopSelf();
}
if (!beaconManager.isBluetoothEnabled()) {
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
} else {
connect();
}
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter
.getDefaultAdapter();
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
beaconManager
.registerMonitoringListener(new BeaconManager.MonitoringListener() {
@OverRide
public void onMonitorStart() {
System.out.println("beacon monitoring start");
}
@OverRide
public void onMonitorStop() {
System.out.println("beacon monitoring stop");
}
@OverRide
public void onRegionEntered(final Region region) {
System.out.println("beacon monitoring region entered");
}
@OverRide
public void onRegionAbandoned(final Region region) {
System.out.println("beacon monitoring abondoned");
}
@OverRide
public void onBeaconAppeared(Region arg0, BeaconDevice beaconDevice) {
System.out.println("beacon monitoring region appeared");
}
@OverRide
public void onBeaconsUpdated(Region arg0, List arg1) {
for(int i = 0; i<arg1.size(); i++){
System.out.println("beacondeviceupdated"+arg1.get(i).getMajor());
if((arg1.get(i).getMajor() == 14096){
if(Util.CAN_TRIGGER_NOTIFICATION){
BeaconDevice beaconDevice = arg1.get(0);
System.out.println("beacon monitoring updated"+arg1.get(0).getMajor());
System.out.println("beaconDevice"+beaconDevice.getMajor());
System.out.println("beaconDevice.getProximity().toString()"+beaconDevice.getProximity().toString());
if(beaconDevice.getProximity().toString().equalsIgnoreCase("immediate")){
if(Util.isNetworkAvailable(ctx)){
showNotifitcation("New Route");
}
else{
switchOnInternet();
}
}
}
}
}
}
});
return START_STICKY;
}
private void connect() {
try {
beaconManager.connect(new OnServiceBoundListener() {
@OverRide
public void onServiceBound() {
try {
beaconManager.startMonitoring();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
}
@OverRide
public void onDestroy() {
super.onDestroy();
beaconManager.stopMonitoring();
beaconManager.disconnect();
beaconManager = null;
}
private void switchOnInternet(){
try{
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);
final ConnectivityManager conman = (ConnectivityManager)
ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field connectivityManagerField =
conmanClass.getDeclaredField("mService");
connectivityManagerField.setAccessible(true);
final Object connectivityManager = connectivityManagerField.get(conman);
final Class connectivityManagerClass =
Class.forName(connectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod =
connectivityManagerClass.getDeclaredMethod("setMobileDataEnabled",
Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(connectivityManager, true);
}
catch(Exception e){
e.printStackTrace();
}
}
public void showNotifitcation(String notify){
final NotificationManager mgr=
(NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification note=new Notification(R.drawable.image,
notify,
System.currentTimeMillis());
// This pending intent will open after notification click
PendingIntent i=PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class),
0);
note.setLatestEventInfo(this, notify,
"test", i);
Vibrator v = (Vibrator)getApplicationContext()
.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
//After uncomment this line you will see number of notification arrived
//note.number=2;
mgr.notify(NOTIFY_ME_ID, note);
}
}
On Mon, Jun 1, 2015 at 5:01 PM, Dawid Gdański [email protected]
wrote:
Hey @mittalprayag25 https://github.com/mittalprayag25 what's the status
of this issue?—
Reply to this email directly or view it on GitHub
https://github.com/kontaktio/Android-SDK/issues/6#issuecomment-107407603
.
from kontakt-android-sdk.
I am also facing an issue with devices. In my nexus 5 Android version 5.1 its working somewhat fine for bindservice but in MotoG Android version 5.0.2 its not. I am getting in onRegionEntered again and again.
from kontakt-android-sdk.
Hey @mittalprayag25 there is nothing we can be helpful with in terms of the SDK performance and behaviour on different Android devices. We are aware of the fact that the behaviour differs but it is heavily dependent on the Android device manufacturer. Particularily, it is up to the Bluetooth Chipset that is installed in the Android device and its manufacturer.
Regarding your issue of Region-specific callbacks being instantly called, it is the filtering configuration combined with MonitorPeriod that causes more frequent invocation of those methods. Lengthening the MonitorPeriod's active scan period should be helpful in your case.
from kontakt-android-sdk.
Hey @mittalprayag25 any problems on that issue?
from kontakt-android-sdk.
Related Issues (20)
- java.util.ConcurrentModificationException at evictInactiveDevices() HOT 2
- MockedImage.java - is it supposed to be there? HOT 3
- Parser.extractFrameData throws an IllegalArgumentException when parsing the results of a scan HOT 5
- Unable to discover beacons in Android 12 with Kontakt SDK >= 5.0.18 HOT 1
- VerifyError exception HOT 4
- Contribution HOT 2
- Diagnostic property code 0x06 HOT 3
- Delete the permission check HOT 3
- Improve logging API HOT 4
- ScanStatusListener.onScanError() improvements HOT 2
- Does't work on Android 12 HOT 2
- New dependency required when updating to version 7.0.2 HOT 8
- BeaconProScanning not working HOT 5
- does not recognize Beacons Pro equipment HOT 14
- Add Battery Level variable in Device class HOT 3
- ErrorCode in KontaktDeviceConnection.ConnectionListener's onErrorOccured HOT 2
- Can't Apply Configuration to a Beacon in Android 13 HOT 2
- regression- startScan failure on Android < 8 HOT 2
- typo in log: "D/SDK: : Stopping monitoring" HOT 3
- Candidate for NPE in InternalProximityManager HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from kontakt-android-sdk.