Downloading Buildings
Once we have a building stored in the NEON Cloud, we want to direct the NEON Location Service to download all the buildings in our area so we can use them for tracking.
We’re going to:
- Create a background
Thread
to handle the potentially heavy network operations of downloading buildings and floorplans. - Create a
Runnable
that, every 5 seconds, pulls the current view bounds from the activity and issues a request to download buildings in that area. - Create an
INeonBuildingListener
that will verify that we have downloaded the buildings that we have created.
Handler and Looper Configuration
First, let’s declare a Handler
that points to the main thread, and a Looper
with an associated Handler
as shown below.
private Handler mainHandler = new Handler(Looper.getMainLooper());
private Looper dataLooper;
private Handler dataHandler;
In our onCreate()
we can start a new Thread
and set the Looper
and Handler
as shown below.
/*
* Create a new background thread, call Looper.prepare() so it
* can handle posts, and grab a dataHandler for loading
* buildings and floor plan images
*/
Thread t = new Thread(new Runnable() {
public void run() {
Looper.prepare();
dataLooper = Looper.myLooper();
dataHandler = new Handler(dataLooper);
Looper.loop();
}
});
t.start();
In our shutdown code we should quit the looper.
private void shutdown()
{
disconnectFromNeonAPI();
if (dataLooper != null) {
dataLooper.quit();
dataLooper = null;
}
}
NEON Building Listener
Next, we should implement INeonBuildingListener
in our activity and an add an onComplete()
method that will be called with a list of buildings as shown below.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, LocationSource, INeonLocationListener, INeonEventListener, INeonBuildingListener {
@Override
public void onComplete(List<NeonBuilding> list, DownloadResult downloadResult) {
if (downloadResult == DownloadResult.SUCCESS)
Log.i("NEONSampleApp", "got " + list.size() +" buildings");
else
Log.i("NEONSampleApp", "result failed with: " + list.toString());
}
...
}
We want to start loading buildings once we have successfully logged into our NEON account, so let’s post a new function that loads buildings on the success event as shown below.
@Override
public void onEvent(NeonEventType type, INeonEvent event) {
Log.i("MapsActivity", "Got an event of type: " + type.toString());
switch (type)
{
case AUTHENTICATION:
AuthenticationEvent ae = (AuthenticationEvent)event;
if (ae.getType() == null)
break;
Log.i("MapsActivity", "Got an event of type: " + ae.getType().toString());
switch (ae.getType())
{
case NO_CREDENTIALS_SET: NeonSettings.startLoginActivityForResult(LOGIN_ACTIVITY_REQUEST_CODE, MapsActivity.this, false); break;
case MANDATORY_UPDATE_REQUIRED: NeonSettings.upgradeNeonLocationServices(MapsActivity.this, true); break;
case UNRESOLVED_AUTHENTICATION_ERROR: Toast.makeText(getApplicationContext(), "Error in login. Please visit NEON Settings page to resolve errors",Toast.LENGTH_LONG).show(); break;
case SUCCESS:
Log.i("MapsActivity", "successfully logged in to Neon Location Service");
//starts loading buildings for display
mainHandler.post(loadBuildingsRunnable);
break;
default: break;
}
break;
default: break;
}
}
/**
* Every five seconds, this runnable will get the area in view on the screen
* and issue a request to download all the buildings for that area.
* The work will be performed on the dataHandler, which points to a background thread.
* Results will be returned on the buildingCallback, where they will be drawn to the screen
* Because the DownloadOption is CACHED, the first request to download buildings in this
* area will take longer as it has to hit the network, but subsequent calls will be much quicker
* since the buildings are already cached in the Neon Location Service.
*/
private Runnable loadBuildingsRunnable = new Runnable() {
@Override
public void run() {
Log.i("MapsActivity", "downloading building");
//get bounds from google map and convert to LatLongRect
final LatLngBounds viewingRect = mMap.getProjection().getVisibleRegion().latLngBounds;
final LatLongRect bounds = new LatLongRect(new LatLong(viewingRect.southwest.latitude, viewingRect.southwest.longitude), new LatLong(viewingRect.northeast.latitude, viewingRect.northeast.longitude));
NeonEnvironment.downloadBuildingsInArea(bounds, dataHandler, MapsActivity.this, DownloadOptions.CACHED);
mainHandler.postDelayed(this, 5000);
}
};
Don’t forget to remove the callback when you shut down.
private void shutdown()
{
disconnectFromNeonAPI();
if (dataLooper != null) {
dataLooper.quit();
dataLooper = null;
}
mainHandler.removeCallbacks(loadBuildingsRunnable);
}