emen
emen

Reputation: 6328

altbeacon - Cannot contact service to set scan periods

I'm using android-beacon-library (altbeacon) to detect beacons around, foreground and background. I used the example shown in Samples. I succeed making it detect one of my beacon, but it doesn't really work well. Sometimes it detects and opens up new activity, and sometimes it doesn't.

Not sure if it was my coding error or something else. As to my understanding, by implementing BeaconManager initialization in Application class, it will automatically scans the beacon once the app is turned on. So, I didn't initialize anything in my Activity class, I just let it scan on Application level.

I've specified my beacon in the Application class via BeaconManager, like so:

public class BeaconReferenceApplication extends Application implements BootstrapNotifier, RangeNotifier {
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "App started up");

        BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
        BeaconManager.setDebug(true);

        beaconManager.getBeaconParsers().add(new BeaconParser().
                setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

        beaconManager.setBackgroundScanPeriod(1100l);

        beaconManager.setBackgroundBetweenScanPeriod(600000l);
        beaconManager.setRangeNotifier(this);

        // Constants is a class containing one of my beacon UUID, major and minor
        Region region = new Region("com.bledemo.com.boostrapRegion", Identifier.parse(Constants.BT_UUID),
                Identifier.fromInt(Constants.BT_MAJOR), Identifier.fromInt(Constants.BT_MINOR));

        regionBootstrap = new RegionBootstrap(this, region);

        backgroundPowerSaver = new BackgroundPowerSaver(this);

        mInstance = this; // Volley networking instance
    }

    // fires up Activity once a specified beacon is detected
    @Override
    public void didEnterRegion(Region region) {
        Log.d(TAG, "Got a didEnterRegion call");

        regionBootstrap.disable();

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("uuid", region.getId1().toString());
        intent.putExtra("major", region.getId2().toString());
        intent.putExtra("minor", region.getId3().toString());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.startActivity(intent);
    }

}

In MainActivity,

public class MainActivity extends Activity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // get intent extras, etc

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.container, fragment)
                    .commit();
        }
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        private static final String TAG = PlaceholderFragment.class.getSimpleName();

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            tvRegion = (TextView) rootView.findViewById(R.id.tvRegion);

            uuid = getArguments().getString("uuid");
            major = getArguments().getString("major");
            minor = getArguments().getString("minor");

            appController = BeaconReferenceApplication.getInstance();

            return rootView;
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

            DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            Date date = new Date();

            if (uuid != null && !uuid.isEmpty()) {
                Log.d(TAG, "uuid not null");

                tvRegion.setText("Beacon found= " + uuid
                                + "\nLast found " + dateFormat.format(date)
                                + "\nSet on 30 mins interval"
                                + "\nRequest to API initiated"
                );

                initBeaconAction(uuid); // init notification
            } else {
                tvRegion.setText("Beacon not found"
                                + "\nLast found " + dateFormat.format(date)
                                + "\nSet on 30 mins interval"
                );
            }
        }
    }

}

In Manifest,

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET"/>

<application
    android:name=".BeaconReferenceApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main"
        android:launchMode="singleInstance" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

As for the error, here is my full logcat debug. As you can see, there is a lot of Cannot contact service to set scan periods. I'm assuming it doesn't do the set scan period correctly.

How can I make it scan when I turn on the app, and also scan it in background when the app is closed?

Upvotes: 0

Views: 2024

Answers (1)

davidgyoung
davidgyoung

Reputation: 65025

The way the code is set up, it will only launch the activity the first time it sees a beacon. This is because the regionBootstrap.disable(); line of code essentially stops beacon detections.

If you take out the line regionBootstrap.disable(); then it will send an intent to launch the activity each time it starts seeing a beacon matching your region. Because you have the activity marked as singleInstance in the manifest, this will re-launch the same activity if it had already been launched.

Upvotes: 1

Related Questions