indooratlas API

Add SDK dependency

For new projects built with Gradle, we recommend using AAR as it is easier to integrate. AAR contains both Java classes and AndroidManifest.xml template which gets merged into your application’s AndroidManifest.xml during build process.

Add this to your build.gradle file.

dependencies {
	compile 'com.indooratlas.android:indooratlas-android-sdk:2.7.0@aar'
}
repositories{
	maven {
		url "http://indooratlas-ltd.bintray.com/mvn-public"
	}
}

We recommend automating dependency management of integrated SDKs such as ours using Gradle as described above. However, if you can not do this, you have an option of manually adding the SDK to your projects, by following the manual installation guide.
Declare sensors
Basic setup

The SDK uses three hardware sensors and Wi-Fi when available. It will function also without some of these sensors to a limited degree, but if your app requires full performance and you’re willing to limit its device compatibility, declaring these in the manifest restricts the devices on which the SDK can be installed from Google Play. You can do this by adding the following declarations to your AndroidManifest.xml before application -element.

<uses-feature android:name="android.hardware.sensor.accelerometer"
	android:required="true" />
<uses-feature android:name="android.hardware.sensor.compass"
	android:required="true" />
<uses-feature android:name="android.hardware.sensor.gyroscope"
	android:required="true" />
<uses-feature android:name="android.hardware.wifi"
	android:required="true" />

Enabling Beacon support

Beacons are not strictly necessary for positioning to work but enabling this feature is recommended for optimal performance.

During runtime, SDK checks if permissions are granted and that Bluetooth service is enabled by the user. Support for beacons is silently ignored if these conditions are not met.

As default, SDK does not add required permissions to scan beacons. To enable support, add the following permissions to your applications AndroidManifest.xml:

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

Add credentials to the Android manifest file

Every application which uses IndoorAtlas service needs a unique ApiKey and Secret strings, which you can manage with IndoorAtlas Applications. See here for further information on API keys.

Add your app credentials as meta-data attributes to AndroidManifest.xml

<application>
	<meta-data
		android:name="com.indooratlas.android.sdk.API_KEY"
		android:value="api-key-here"/>
	<meta-data
		android:name="com.indooratlas.android.sdk.API_SECRET"
		android:value="api-secret-here"/>
</application>

Getting user’s permission (Android 6+)

Before you can use IndoorAtlas location framework on Android versions 6 and above, your application will need to get user’s permission for coarse location and Wi-Fi status. You can accomplish this in your application’s main Activity:

private final int CODE_PERMISSIONS = //...

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	String[] neededPermissions = {
		Manifest.permission.CHANGE_WIFI_STATE,
		Manifest.permission.ACCESS_WIFI_STATE,
		Manifest.permission.ACCESS_COARSE_LOCATION
	};
	ActivityCompat.requestPermissions( this, neededPermissions, CODE_PERMISSIONS );
}

//...

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
	super.onRequestPermissionsResult(requestCode, permissions, grantResults);

	//Handle if any of the permissions are denied, in grantResults
}

The central component of the IndoorAtlas location framework is the IALocationManager class, which provides access to IndoorAtlas services. The methods of this class must be called from the main thread only.

Create a new instance of IALocationManager using its create() method. If you are using an Activity, your activity’s onCreate() is a good place to do this:

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

    mIALocationManager = IALocationManager.create(this);
}

Now you can register and unregister for periodic updates of the user’s current location.

The automatic recognition of floor plans, locations (a.k.a. venues) and indoor-outdoor-transitions are handled in the IndoorAtlas SDK with IARegion events

/** Minimal floor detection example */
private IARegion.Listener mRegionListener = new IARegion.Listener() {
    IARegion mCurrentFloorPlan = null;

    @Override
    public void onEnterRegion(IARegion region) {
        if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
            Log.d(TAG, "Entered " + region.getName());
            Log.d(TAG, "floor plan ID: " + region.getId());
            mCurrentFloorPlan = region;
        }
    }

    @Override
    public void onExitRegion(IARegion region) {}
};

Region listeners are also registered to the IALocationManager

mIALocationManager.registerRegionListener(mRegionListener);

Disabling automatic floor detection

Even though this is not recommended, you can substitute IndoorAtlas floor detectionwith your own by providing an explicit floor plan (IARegion.floorPlan) with the setLocation method.This will lock the position into that floor until you provide another floor plan ID.


After creating the IALocationManager , you can register and unregister for periodic updates of the user’s current location. To this end, you have to implement the IALocationListener interface and override its onLocationChanged() callback method. This is the place where your location updates will be delivered as IALocation objects

private IALocationListener mIALocationListener = new IALocationListener() {

    // Called when the location has changed.
    @Override
    public void onLocationChanged(IALocation location) {

        Log.d(TAG, "Latitude: " + location.getLatitude());
        Log.d(TAG, "Longitude: " + location.getLongitude());
        Log.d(TAG, "Floor number: " + location.getFloorLevel());
    }
};

To start receiving location updates you also have to call the requestLocationUpdates() method, where you provide an instance of IALocationRequest as a parameter. It may include extra options for location manager. You may consider doing this e.g. in your activity’s onResume() and onPause() methods respectively.

@Override
protected void onResume() {
    super.onResume();
    mIALocationManager.requestLocationUpdates(IALocationRequest.create(), mIALocationListener);
}

Tip:Indoor-outdoor transitions are demonstrated in the Google Maps Overlay code example

Accurate indoor-outdoor detection requires GPS. In IndoorAtlas SDK versions 2.6 and above,the platform location scanning needed for this purpose is managed by the SDK, but youneed to provide the necessary permissions:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Also remember to query for the user’s permission as described in theSDK setup section.

Indoor-outdoor detection is also available in SDK versions 2.3 and above butin versions <= 2.5, you need to manually request for GPS platform locations touse it. The IndoorAtlas SDK will then listen the updates using a PASSIVE_PROVIDER.

Like automatic floor detection, Indoor-outdoor transitions are signaled with the IARegion events.

private IARegion.Listener mRegionListener = new IARegion.Listener() {
    // when null, we are not on any mapped area
    // this information can be used for indoor-outdoor detection
    IARegion mCurrentFloorPlan = null;

    @Override
    public void onEnterRegion(IARegion region) {
        if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
            // triggered when entering the mapped area of the given floor plan
            Log.d(TAG, "Entered " + region.getName());
            Log.d(TAG, "floor plan ID: " + region.getId());
            mCurrentFloorPlan = region;
        }
        else if (region.getType() == IARegion.TYPE_VENUE) {
            // triggered when near a new location
            Log.d(TAG, "Location changed to " + region.getId());
        }
    }

    @Override
    public void onExitRegion(IARegion region) {
        // leaving a previously entered region
        if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
            mCurrentFloorPlan = null;
            // notice that a change of floor plan (e.g., floor change)
            // is signaled by an exit-enter pair so ending up here
            // does not yet mean that the device is outside any mapped area
        }
    }
};

Region listeners must be registered to the IALocationManager

mIALocationManager.registerRegionListener(mRegionListener);

Location and floor plan regions

In the above code snippet, there are two types of region entry events. TheTYPE_FLOOR_PLAN entry events are triggered when the user actually enters themapped area of the floor plan. In almost all cases, this corresponds tophysically entering the building.The TYPE_VENUE events are emitted a lot earlier, between 100 and 200 metersof the location (a.k.a. venue). This is meant as aheads-up to enable pre-loading of data. The venue entry events are also useful inthe case when one wishes to disable automatic indoor-outdoor detection.

Floor plan and venue regions

Disabling indoor-outdoor detection

Automatic indoor-outdoor detection can be disabled by calling setLocation methodof IALocationManager with an explicit venue (IARegion.venue) or floor plan (IARegion.floorPlan).This tells the SDK that you are certain that the user is inside the given building.

Even if you with to disable IndoorAtlas indoor-outdoor detection, you can still enable automatic floor detection by locking the first detected venue as follows:

private IARegion.Listener mRegionListener = new IARegion.Listener() {
    IARegion mCurrentVenue = null;
    IARegion mCurrentFloorPlan = null;

    @Override
    public void onEnterRegion(IARegion region) {
        if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
            // automatically detected floor plan
            mCurrentFloorPlan = region;
        }
        else if (region.getType() == IARegion.TYPE_VENUE) {
          if (mCurrentVenue == null) {
            // lock to the first detected venue
            mIALocationManager.setLocation(IALocation.Builder()
                .withRegion(region).build());
          }
          mCurrentVenue = region;
        }
    }

    @Override
    public void onExitRegion(IARegion region) {}
};


Automatic floor plan detection is handled with IARegion events as described in the floor detection chapter. For your convenience, IndoorAtlas SDK also provides an API for fetching the floor plan images that you have stored in our cloud in the mapping phase.

If you use an indoor map provider such as Micello, you probably want to skip this and use their API for displaying the floor plan instead.

  • An ImageView instance is created in the application layout resource file. It will hold the bitmap image, when we get it.
  • The IAFloorPlan class represents floor plan data. It has a url field pointing to the floor plan image.
  • The IAResourceManager class provides an interface to fetch IAFloorPlan objects from IndoorAtlas services.

Create an instance of the IAResourceManager class using its create() method.

public class ResourceManagerActivity extends AppCompatActivity {
    private IALocationManager mLocationManager;
    private IAResourceManager mResourceManager;
    private ImageView mFloorPlanImage;

    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_floor_plan_manager);
        mFloorPlanImage = (ImageView) findViewById(R.id.image);
        // ...
        // Create instance of IAResourceManager class
        mResourceManager = IAResourceManager.create(this);
    }
}

Register a Region listener:

private IARegion.Listener mRegionListener = new IARegion.Listener() {
    @Override
    public void onEnterRegion(IARegion region) {
        if (region.getType() == IARegion.TYPE_FLOOR_PLAN) {
            fetchFloorPlan(region.getId());
        }
    }

    @Override
    public void onExitRegion(IARegion region) {
        // leaving a previously entered region
    }
};

mIALocationManager.registerRegionListener(mRegionListener);

Request location updates

To fetch the floor plan, call the fetchFloorPlanWithId() method of the IAResourceManager class. It returns an instance of IATask<IAFloorPlan>.IATask<R> and IAResultCallback<R> are helper interfaces to work with asynchronous operations.

private void fetchFloorPlan(String id) {
    // Cancel pending operation, if any
    if (mPendingAsyncResult != null && !mPendingAsyncResult.isCancelled()) {
        mPendingAsyncResult.cancel();
    }

    mPendingAsyncResult = mResourceManager.fetchFloorPlanWithId(id);
    if (mPendingAsyncResult != null) {
        mPendingAsyncResult.setCallback(new IAResultCallback<IAFloorPlan>() {
            @Override
            public void onResult(IAResult<IAFloorPlan> result) {
                Logger.d(TAG, "onResult: %s", result);

                if (result.isSuccess()) {
                    handleFloorPlanChange(result.getResult());
                } else {
                    // do something with error
                    Toast.makeText(FloorPlanManagerActivity.this,
                        "loading floor plan failed: " + result.getError(), Toast.LENGTH_LONG)
                        .show();
                }
            }
        }, Looper.getMainLooper()); // deliver callbacks in main thread
    }
}

If we don’t have any errors, download the image. For convenience here, we use the third-party Picasso library.

import com.squareup.picasso.Picasso;
// ...
private void handleFloorPlanChange(IAFloorPlan newFloorPlan) {
    Picasso.with(this)
        .load(newFloorPlan.url)
        .into(mFloorPlanImage);
}

Tip:Wayfinding is demonstrated in Wayfinding code example

Wayfinding is done on a graph created by the IA wayfinding graph editor (see Wayfinding graph).

To use the IndoorAtlas Wayfinding in your project, you need to first setup the positioning SDK. After this, you need to add the dependencies to IndoorAtlas Wayfinding

dependencies {
    compile 'com.indooratlas.android:indooratlas-android-wayfinding:2.7.0@aar'
}

Using the wayfinder

To begin, first initialize the IndoorAtlas positioning SDK with valid credentials

// Initialize the IALocationManger
IALocationManager mLocationManager = IALocationManager.create(context, extras);

Then initialize the IndoorAtlas wayfinder (IAWayfinder) using the wayfinding graph together with the application context:

// Load the JSON file to String graphJSON
IAWayfinder wayfinder = IAWayfinder.create(context, graphJson);

To start routing an user to a given destination, first set the destination in the wayfinder:

// Set the latitude, longitude and floor number
wayfinder.setDestination(60.1684003, 24.9306895, 1);

The route from the current location to destination is obtained by first setting the user’s location and then calling getRoute:

// Set the latitude, longitude and floor number
wayfinder.setLocation(60.1696597, 24.932497, 1);
IARoutingLeg[] route = wayfinder.getRoute();
// empty if route could not be found, otherwise list of legs

Example route in Kamppi center

Route is a list of legs where each leg is a straight line segment. The legs also contain pointers to the original nodes and edges of the wayfinding graph, to allow linking to possibly relevant meta data, but using that information is often not mandatory. One leg (IARoutingLeg) in the route list contains the following variables:

IARoutingPoint begin;
IARoutingPoint end;
double length;
double direction;
java.lang.Integer edgeIndex;

where the IARoutingPoints contain the following variables:

double latitude;
double longitude;
int floor;
java.lang.Integer nodeIndex;

The variables edgeIndex and nodeIndex point to edges and nodes in the original graph. Note that the index variables can be null for the first and last legs of the route, that present the final connections between the graph and arbitrary off-graph locations.

The begin node of the first leg is always the starting location and the end node of the last leg is the destination. The returned route can also be empty if no possible route was found. This can happen if the given destination or start location floor number does not exist in the wayfinding graph (e.g., if one would do something like wayfinder.setLocation(60.2, 24.9, 1000);).


To stop receiving updates, call the removeLocationUpdates() method.

@Override
protected void onPause() {
    super.onPause();
    mIALocationManager.removeLocationUpdates(mIALocationListener);
}

When you are done with the location service, destroy the instance of IALocationManager to release the allocated resources.

@Override
protected void onDestroy() {
    mIALocationManager.destroy();
    super.onDestroy();
}



 

猜你喜欢

转载自blog.csdn.net/liudongdong19/article/details/80200877
API
今日推荐