Git Product home page Git Product logo

Comments (8)

dawidgdanski avatar dawidgdanski commented on July 27, 2024

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.

mittalprayag25 avatar mittalprayag25 commented on July 27, 2024

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.

dawidgdanski avatar dawidgdanski commented on July 27, 2024
  1. You specify Monitor Period with 5s of active scan duration and 5s of passive scan duration.
  2. 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.

dawidgdanski avatar dawidgdanski commented on July 27, 2024

Hey @mittalprayag25 what's the status of this issue?

from kontakt-android-sdk.

mittalprayag25 avatar mittalprayag25 commented on July 27, 2024

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.

mittalprayag25 avatar mittalprayag25 commented on July 27, 2024

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.

dawidgdanski avatar dawidgdanski commented on July 27, 2024

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.

dawidgdanski avatar dawidgdanski commented on July 27, 2024

Hey @mittalprayag25 any problems on that issue?

from kontakt-android-sdk.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.