0

I am doing an indoor localization app which is based on beacons. In my application, I have loaded 3 tabs in a ViewPager. The 2nd tab is a Map fragment which should display the map of the location the user is in based on the beacon signal.

public class Shop extends AppCompatActivity implements IndoorsLocationListener, ProximityManager.ProximityListener {

    private static final String TAG = Shop.class.getSimpleName();
    private IndoorsSurfaceFragment indoorsFragment;
    private ProximityManagerContract proximityManager;
    private ScanContext scanContext;
    TabPagerAdapter adapter;
    ViewPager viewPager;


    // TODO : Add more event types like devices updated
    private List<EventType> eventTypes = new ArrayList<EventType>() {{
//        add(EventType.DEVICES_UPDATE);
        add(EventType.DEVICE_DISCOVERED);
    }};

    private IBeaconScanContext beaconScanContext = new IBeaconScanContext.Builder()
            .setEventTypes(eventTypes) //only specified events we be called on callback
            .setRssiCalculator(RssiCalculators.newLimitedMeanRssiCalculator(5))
            .build();

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

        proximityManager = new KontaktProximityManager(this);

        setContentView(R.layout.activity_shop);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        setTitle("Shopping");

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();


        viewPager = (ViewPager) findViewById(R.id.tab_content);

        MapTabContentFragment mtcf = new MapTabContentFragment();
        adapter = new TabPagerAdapter(getSupportFragmentManager());

        IndoorsFactory.Builder indoorsBuilder = new IndoorsFactory.Builder();
        IndoorsSurfaceFactory.Builder surfaceBuilder = new IndoorsSurfaceFactory.Builder();
        indoorsBuilder.setContext(this);

        // Set the API Key for Indoo.rs
        indoorsBuilder.setApiKey(getResources().getString(R.string.indoors_api_key));

        // Set the building's ID
        indoorsBuilder.setBuildingId((long)762751544);
        // Log.d(TAG+ " Building ID: ", Long.toString(pBuildingID));

        // callback for indoo.rs-events
        indoorsBuilder.setUserInteractionListener(this);
        surfaceBuilder.setIndoorsBuilder(indoorsBuilder);
        indoorsFragment = surfaceBuilder.build();

        adapter.addFragment(new ListTabContentFragment(), "LIST");
        adapter.addFragment(indoorsFragment, "MAP");
        adapter.addFragment(new ARTabContentFragment(), "AR");

        viewPager.setAdapter(adapter);
  }
}

This code segment just loads all the tabs at once when the activity is created. Now what I need is the 2nd fragment (mtcf, "MAP") to load only when the beacons signal is received.

@Override
public void onEvent(BluetoothDeviceEvent bluetoothDeviceEvent) {
    List<? extends RemoteBluetoothDevice> deviceList = bluetoothDeviceEvent.getDeviceList();
    long timestamp = bluetoothDeviceEvent.getTimestamp();
    DeviceProfile deviceProfile = bluetoothDeviceEvent.getDeviceProfile();
    switch (bluetoothDeviceEvent.getEventType()) {
        case SPACE_ENTERED:
            Log.d(TAG, "namespace or region entered");
            break;
        case DEVICE_DISCOVERED:
            Log.d(TAG, "found new beacon");
            Log.d(TAG, ((Integer.toString(deviceList.size()))));

            String nameOfBeacon = deviceList.get(0).getName();

            if(nameOfBeacon.equals("Entrance")) {
                long buildingMapID = lookupBuilding(deviceList.get(0).getName());
                IndoorsSurfaceFragment indoorsSurfaceFragment = createIndoorFragment(buildingMapID);

                getSupportFragmentManager().beginTransaction().replace(R.id.indoorslayout,indoorsSurfaceFragment).commit();
            }
            break;

MapFragment.xml

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<FrameLayout
    android:id="@+id/indoorslayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></FrameLayout>

</android.support.v4.widget.NestedScrollView>`

How can I implement this?? I need the map fragment to load only after the Bluetooth beacon event is received.

Thanks.

Yasir Tahir
  • 790
  • 1
  • 11
  • 31
FireDrakon
  • 275
  • 2
  • 6
  • 19

2 Answers2

2

You must handle it by your TabPagerAdapter:

1, In TabPagerAdapter, add a param, like : List<Fragment> mItems, first you add two fragments into mItems.

override TabPagerAdaptergetItem function like this:

 public Fragment getItem(int position){
     return mItems.get(position);
}

2, When you want to show MapFragment, just by TabPagerAdapter addItem function, then mItems have three fragments. You can manually sort fragments.

When you use addItem, don't forget to call notifyDataSetChanged(). Hope to help you!

yanzi1225627
  • 893
  • 11
  • 13
  • Been searching along the wrong way for the last two days. Thanks again. – FireDrakon May 24 '16 at 06:36
  • There is one more problem. Is it possible to replace a new fragment with an old one? I tried something like this. mFragmentList.set(1,newFragment); But it is not getting updated. I have called the notifyDataSetChanged() function also. Any reason why? – FireDrakon May 24 '16 at 07:00
  • Yes, `notifyDataSetChanged()` always don't work, when your adapter extends `FragmentPagerAdapter`. You should override `getItemPosition`, and return `POSITION_NONE`. You can refer:[this](http://stackoverflow.com/questions/10849552/update-viewpager-dynamically) – yanzi1225627 May 24 '16 at 07:44
1

You need to invoke notifyDataSetChanged inside "OnEvent" , and implement getItemPosition(Object map) in Viewpager.

This will update the map page everytime you invode notifyDatasetChanged Update Fragment from ViewPager

Community
  • 1
  • 1
Ashish Rawat
  • 5,541
  • 1
  • 20
  • 17