首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Android iBeacons AltBeacon库获取连续的AltBeacon信息

从Android iBeacons AltBeacon库获取连续的AltBeacon信息
EN

Stack Overflow用户
提问于 2015-03-08 19:30:07
回答 2查看 1.5K关注 0票数 0

我正在用AltBeacon库从RadiusNetworks开发一个安卓应用程序。我使用导航抽屉(启动活动,而不是碎片)来显示不同的部分。因此,我有一个主要的活动抽屉,启动不同的活动,通过意图。

我想让附近的iBeacons信息( in和距离)在应用程序中随处可见。怎样才能做到这一点?

我尝试了以下方法(如果我们用RadiusNetworks提供的参考结构映射我的应用程序结构):

  • BeaconReferenceApp:与参考应用程序相同。启动MainActivity。
  • MainActivity:我合并了监视和测距活动。这项活动还管理导航抽屉。
  • Section1:这个扩展了MainActivity,并根据iBeacons收集的数据显示了一些信息。

在MainActivity中,我执行以下操作:

代码语言:javascript
复制
public void onBeaconServiceConnect() {
        beaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                for (Beacon beacon : beacons) {
                    Log.i("TAG","Beacon detected with id1: "+beacon.getId1()+" id2:"+beacon.getId2()+" id3: "+beacon.getId3()+" distance: "+beacon.getDistance());
                }
            }

        });

        try {
            beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
        } catch (RemoteException e) {   }
    }

我可以在日志中看到iBeacon信息,但只看到一次(第一次检测)。然而,我想要不断地得到这个信息,每次看到iBeacon (就像在参考应用程序中发生的那样),这样我就可以把它传递给我的其他活动。

我怎么才能解决这个问题?我应该使用不同的应用程序结构(因为导航抽屉),还是我在错误地使用库?

谢谢。

更新: MainActivity和BeaconReferenceApp的代码。

BeaconReferenceApp:

代码语言:javascript
复制
public class BeaconReferenceApp extends Application implements BootstrapNotifier {

    private static final String TAG = "BeaconApp";
    private RegionBootstrap regionBootstrap;
    private BackgroundPowerSaver backgroundPowerSaver;
    private boolean haveDetectedBeaconsSinceBoot = false;
    private MainActivity mainActivity = null;

    public void onCreate() {
        super.onCreate();
        BeaconManager 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,d:25-25"));


        Log.d(TAG, "setting up background monitoring for beacons and power saving");
        // wake up the app when a beacon is seen
        Region region = new Region("backgroundRegion", null, null, null);
        regionBootstrap = new RegionBootstrap(this, region);
        backgroundPowerSaver = new BackgroundPowerSaver(this);
    }

  public void didEnterRegion(Region arg0) {

        Log.d(TAG, "did enter region.");
        // regionBootstrap.disable();
        if (!haveDetectedBeaconsSinceBoot) {
            Log.d(TAG, "auto launching MainActivity");

            // The very first time since boot that we detect an beacon, we launch the MainActivity
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            this.startActivity(intent);
            haveDetectedBeaconsSinceBoot = true;
        } else {

               sendNotification();
        }

    }

public void didExitRegion(Region region) {}
public void didDetermineStateForRegion(int state, Region region) {}
public void setMainActivity(MainActivity activity) {this.mainActivity = activity;}

MainActivity:

代码语言:javascript
复制
public class MainActivity extends ActionBarActivity implements BeaconConsumer {

    protected FrameLayout frameLayout;
    protected ListView mDrawerList;
    protected String[] listArray = { "Item1", "Item2", "Item3", "Item4" };
    protected static int position;
    private static boolean isLaunch = true;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    private BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        verifyBluetooth();
        beaconManager.bind(this);

        setContentView(R.layout.navigation_drawer_base_layout);

        frameLayout = (FrameLayout)findViewById(R.id.content_frame);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // set up the drawer's list view with items and click listener
        mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, listArray));
        mDrawerList.setOnItemClickListener(new OnItemClickListener() {

            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {

                openActivity(position);
            }
        });

        // enable ActionBar app icon to behave as action to toggle nav drawer
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the proper interactions between the sliding drawer and the action bar app icon
        actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,                       /* host Activity */
                mDrawerLayout,              /* DrawerLayout object */
                R.string.open_drawer,       /* "open drawer" description for accessibility */
                R.string.close_drawer)      /* "close drawer" description for accessibility */
        {

            public void onDrawerClosed(View drawerView) {
                getSupportActionBar().setTitle(listArray[position]);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                super.onDrawerClosed(drawerView);
            }

            public void onDrawerOpened(View drawerView) {
                getSupportActionBar().setTitle(getString(R.string.app_name));
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                super.onDrawerOpened(drawerView);
            }

            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }

            public void onDrawerStateChanged(int newState) {
                super.onDrawerStateChanged(newState);
            }
        };
        actionBarDrawerToggle.syncState();
        mDrawerLayout.setDrawerListener(actionBarDrawerToggle);


        /**
         * MainActivity is intended just to add navigation drawer in the app.
         * Open some activity with layout on launch. Check checking if this 
         * MainActivity is called first time when we are
         * opening our first activity.
         * */
        if(isLaunch){
            /**
             *Setting this flag false so that next time it will not open
             * first activity.
             * Use this flag because we are using MainActivity
             * as parent activity to our other activities.
             * In this case this base activity will always be call when any
             * child activity will launch.
             */
            isLaunch = false;
            openActivity(0);
        }
    }

    /**
     * Launching activity when any list item is clicked.
     */
    protected void openActivity(int position) {

        mDrawerLayout.closeDrawer(mDrawerList);
        MainActivity.position = position; //Setting currently selected position in this field so that it will be available in child activities.

        switch (position) {
            case 0:
                startActivity(new Intent(this, Item1.class));
                break;
            case 1:
                startActivity(new Intent(this, Item2.class));
                break;
            case 2:
                startActivity(new Intent(this, Item3.class));
                break;
            case 3:
                startActivity(new Intent(this, Item4.class));
                break;
            default:
                break;
        }
    }

    public void onDestroy() {
        super.onDestroy();
        beaconManager.unbind(this);
    }

    public void onResume() {
        super.onResume();
        ((BeaconReferenceApp) this.getApplicationContext()).setMainActivity(this);
        if (beaconManager.isBound(this)) beaconManager.setBackgroundMode(false);
    }

    public void onPause() {
        super.onPause();
        ((BeaconReferenceApp) this.getApplicationContext()).setMainActivity(null);
        if (beaconManager.isBound(this)) beaconManager.setBackgroundMode(true);
    }

    private void verifyBluetooth() {}

    public void onBeaconServiceConnect() {
        beaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                for (Beacon beacon : beacons) {
                    Log.i("TAG", "Beacon detected with id1: " + beacon.getId1() + " id2:" + beacon.getId2() + " id3: " + beacon.getId3() + " distance: " + beacon.getDistance());
                }
            }

        });

        try {
            beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
        } catch (RemoteException e) {   }
    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-14 16:00:45

我已经解决了修改信标类的问题(我只显示了更改):

代码语言:javascript
复制
public class Beaconing extends Application implements BootstrapNotifier, BeaconConsumer {

....

private BeaconManager beaconManager = null;

....

public void onCreate() {
        super.onCreate();
        beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);

....

}

....

public void onBeaconServiceConnect() {
    beaconManager.setBackgroundMode(true);
}

因此,我实现了BeaconConsumer,将beaconManager设置为null,并在onCreate()中获得了它,并添加了onBeaconServiceConnect()。

这种方式对我有效,我实际上得到了连续的距离。

尽管如此,我还是不知道为什么它以前不起作用。如果有人知道并解释的话,我会很高兴的。

谢谢@davidgyoung (https://stackoverflow.com/users/1461050/davidgyoung)您的帮助!:)

票数 1
EN

Stack Overflow用户

发布于 2015-03-08 20:22:20

最简单的方法是在自定义的android.app.Application类中进行测距。每个Android应用程序都有其中的一个,这是一个很好的地方,你想把代码全球化到整个应用程序。要定义您自己的此类类,可以在清单中通过向以下内容添加一个属性来声明它:

代码语言:javascript
复制
<application
    ...
    android:name="MyApplication">

然后,您可以定义一个名称相同的类,其范围如下:

代码语言:javascript
复制
public class MyApplication extends Application implements BeaconConsumer {
    private BeaconManager mBeaconManager;

    public void onCreate() {
        super.onCreate();
        mbeaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
        mBeaconManager.bind(this);
    }
    public void onBeaconServiceConnect() {
        mBeaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                for (Beacon beacon : beacons) {
                    Log.i("TAG","Beacon detected with id1: "+beacon.getId1()+" id2:"+beacon.getId2()+" id3: "+beacon.getId3()+" distance: "+beacon.getDistance());
                }
            }

        });

        try {
            mBeaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
        } catch (RemoteException e) {   }
    }

如果您可以在Application类中执行所有逻辑,则只需这样做。但是,您可能需要将范围数据转发到单个活动或片段。如果是这样的话,最简单的方法是从片段或这样的活动中获得对中央Application类的引用:

代码语言:javascript
复制
MyApplication myApplication = ((MyApplication)this.getApplication());

然后,您可以从Application类访问集中存储的数据,或者告诉Application类将didRangeBeaconsInRegion回调转发给您的活动或片段。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28930926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档