Estimote / Android-Fleet-Management-SDK

Estimote Fleet Management SDK for Android
https://developer.estimote.com
MIT License
836 stars 451 forks source link

onBeaconDiscovered-results in non-ui thread #104

Closed RediOne1 closed 8 years ago

RediOne1 commented 9 years ago

When writing, my application, I noticed that the main thread blocks, when method onBeaconDiscovered doing more work. In onBeaconDiscovered I wrote this:

@Override
public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
    if(Looper.myLooper() == Looper.getMainLooper())
        Log.d("DEBUG_TAG", "MainThread");
    else
        Log.d("DEBUG_TAG", "SeparateThread");

        ...
}

to check, if the results are delivered on non-ui thread, as it is writen in sample code in documentation:

@Override
public void onBeaconsDiscovered(Region region, final List<Beacon> rangedBeacons) {
    // Note that results are not delivered on UI thread.
    runOnUiThread(new Runnable() {
     ...

but the results of log was "MainThread". I'm using beaconManager in custom service, which is working even the app is closed, or phone is restarted. It is possible to recive onBeaconDiscovered results in non-ui thread, or it is something wrong in my code. This is my simplified Service code:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class MyBeaconScanner extends Service implements BeaconManager.MonitoringListener, BeaconManager.RangingListener {

    private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", null, null, null);

    private static BeaconManager beaconManager = null;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (beaconManager == null)
            startMonitoringService();

        return Service.START_STICKY;
    }

    private void startMonitoringService() {
        beaconManager = new BeaconManager(this);
        beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0);
        beaconManager.setMonitoringListener(this);
        beaconManager.setRangingListener(this);
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                try {
                    beaconManager.startMonitoring(ALL_ESTIMOTE_BEACONS);
                } catch (RemoteException e) {
                    Log.e("BEACONS", "Cannot start ranging", e);
                }
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            beaconManager.stopMonitoring(ALL_ESTIMOTE_BEACONS);
            beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
        } catch (RemoteException e) {
            Log.e("BEACONS", "Cannot stop but it does not matter now", e);
        }
        beaconManager.disconnect();
        beaconManager = null;
    }

    @Override
    public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {

        doSomething();
    }

    @Override
    public void onEnteredRegion(Region region, List<Beacon> beacons) {
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                try {
                    beaconManager.startRanging(ALL_ESTIMOTE_BEACONS);
                } catch (RemoteException e) {
                    Log.e("BEACONS", "Cannot start ranging", e);
                }
            }
        });
    }

    @Override
    public void onExitedRegion(Region region) {
        try {
            beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}
wiktor commented 9 years ago

Which Android version?

On Wed, Mar 25, 2015 at 11:30 AM, RediOne1 notifications@github.com wrote:

When writing, my application, I noticed that the main thread blocks, when method onBeaconDiscovered doing more work. In onBeaconDiscovered I wrote this:

@Override
public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
  if(Looper.myLooper() == Looper.getMainLooper())
      Log.d("DEBUG_TAG", "MainThread");
  else
      Log.d("DEBUG_TAG", "SeparateThread");
      ...
}

to check, if the results are delivered on non-ui thread, as it is writen in sample code in documentation:

@Override
      public void onBeaconsDiscovered(Region region, final List<Beacon> rangedBeacons) {
        // Note that results are not delivered on UI thread.
        runOnUiThread(new Runnable() {
     ...

but the results of log was "MainThread". I'm using beaconManager in custom service, which is working even the app is closed, or phone is restarted. It is possible recive onBeaconDiscovered results in non-ui thread, or it is something wrong in my code. This is my simplified Service code:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MyBeaconScanner extends Service implements BeaconManager.MonitoringListener, BeaconManager.RangingListener {
  private static final Region ALL_ESTIMOTE_BEACONS = new Region("regionId", null, null, null);
  private static BeaconManager beaconManager = null;
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      if (beaconManager == null)
          startMonitoringService();
      return Service.START_STICKY;
  }
  private void startMonitoringService() {
      beaconManager = new BeaconManager(this);
      beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0);
      beaconManager.setMonitoringListener(this);
      beaconManager.setRangingListener(this);
      beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
          @Override
          public void onServiceReady() {
              try {
                  beaconManager.startMonitoring(ALL_ESTIMOTE_BEACONS);
              } catch (RemoteException e) {
                  Log.e("BEACONS", "Cannot start ranging", e);
              }
          }
      });
  }
  @Override
  public void onDestroy() {
      super.onDestroy();
      try {
          beaconManager.stopMonitoring(ALL_ESTIMOTE_BEACONS);
          beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
      } catch (RemoteException e) {
          Log.e("BEACONS", "Cannot stop but it does not matter now", e);
      }
      beaconManager.disconnect();
      beaconManager = null;
  }
  @Override
  public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
      doSomething();
  }
  @Override
  public void onEnteredRegion(Region region, List<Beacon> beacons) {
      beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
          @Override
          public void onServiceReady() {
              try {
                  beaconManager.startRanging(ALL_ESTIMOTE_BEACONS);
              } catch (RemoteException e) {
                  Log.e("BEACONS", "Cannot start ranging", e);
              }
          }
      });
  }
  @Override
  public void onExitedRegion(Region region) {
      try {
          beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS);
      } catch (RemoteException e) {
          e.printStackTrace();
      }
  }
  @Override
  public IBinder onBind(Intent intent) {
      return null;
  }

}

Reply to this email directly or view it on GitHub: https://github.com/Estimote/Android-SDK/issues/104

RediOne1 commented 9 years ago

5.0

wiktor commented 9 years ago

This is regression on Android 5, before it wasn't delivered on UI thread. Fixing this will take a bit more time.

jtrollia commented 9 years ago

Hello,

I have the same problem here. I work on 5.1 Any news?

wiktor commented 9 years ago

@Malivuk Not yet. Note that this is not crucial or introducing any bugs. This will not cause any problems in your app.

jtrollia commented 9 years ago

Sure there is no bug but my app relies on a background service that detects if someone stay nearby a beacon area for few minutes.

I'm afraid there is no workaround for me.

wiktor commented 9 years ago

@Malivuk There is a workaround. When callback is invoked like onBeaconsDiscovered just invoke code block in a background thread and that's perfectly fine.

Can you elaborate why invoking it on main thread causes problem for you?

jtrollia commented 9 years ago

Ok I'll try some different ways. I was just trying to follow some best practices and put all my beacon related code into a service but maybe I'm wrong.

If such code is called from the main thread, it will be killed if the app is killed as well, right?

manoj192 commented 7 years ago

@Malivuk

    beaconManager.setRangingListener(this) does't give result for specific device(Micromax q439) i checked SystemRequirementsChecker.checkWithDefaultDialogs(HomeActivity.this) also .

Note : my region request private static Region BEACONS= new Region("regionId", null, null, null);

        Android 6