Quick Start
Sample project
We build up a sample scaffold project to kick off your project as smoothly as possible.
Caution
The SDK library is always improving. For the latest developments and features please check Release Notes.
Minimal requirements
- Android Studio
- Android device or emulator running API 23 and above
- Since this is an offline maps-based SDK, sufficient space on internal or external storage is required
Adding the library to your project
Add this piece of code to settings.gradle
dependencyResolutionManagement {
..
repositories {
..
maven {
url "https://sdk.mapfactor.com/repo/release"
credentials {
username "$mavenUsername"
password "$mavenPassword"
}
}
}
}
or build.gradle
for older projects
allprojects {
repositories {
..
maven {
url "https://sdk.mapfactor.com/repo/release"
credentials {
username "$mavenUsername"
password "$mavenPassword"
}
}
}
}
Edit your gradle.properties
mavenUsername=askForUsername
mavenPassword=askForPassword
Username and password will be provided by our sales department.
Configure your build.gradle
dependencies {
implementation "com.mapfactor:sdk:x.y.z"
}
Please check Release Notes to find out the current version of the library.
Initialization
To ensure our SDK works properly, add dependencies to a build.gradle
:
implementation "androidx.compose.ui:ui-viewbinding:x.y.z"
implementation "androidx.fragment:fragment-ktx:x.y.z"
implementation 'androidx.constraintlayout:constraintlayout:x.y.z'
buildFeatures {
viewBinding true
}
You will need to add permissions to access device location to AndroidManifest.xml
as follows.
<manifest..>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<manifest>
The key to run our SDK is MpfcEngine’s init
method.
// get path
val sdkDataPath = getExternalFilesDir(null).toString()
// get renderer
val rendererName: RendererName = RendererName.HARDWARE
// get map data provider
val mapDataProvider: ProviderName = ProviderName.OSM
//get language
val lang = "en"
MpfcEngine.getInstance().init(this, sdkDataPath, mapDataProvider, rendererName, lang, object :
MpfcEngine.InitListener {
override fun onLocationPermissionNotGranted() {
}
override fun onEngineInitStatusChanged(initStatus: MpfcEngine.InitStatus) {
}
override fun onEngineInitFinished(initStatusResult: MpfcEngine.InitResult) {
if (result == MpfcEngine.InitResult.SUCCESS) {
//HURAYYY, do whatever you want, e.g.
initActiveVehicle()
getAllAvailableVehicles()
setCurrentLanguage()
} else if (result == MpfcEngine.InitResult.FAILED_DEVICE_NOT_ACTIVATED) {
//oops, activate device
activateDevice()
}
}
})
fun activateDevice() {
MpfcEngine.getInstance().activateDevice(
"AAAAA-BBBBB-CCCCC-DDDDD-EEEEE"
) { activationResult: MpfcEngine.ActivationResult ->
val succeeded =
activationResult == MpfcEngine.ActivationResult.SUCCEEDED ||
activationResult == MpfcEngine.ActivationResult.ALREADY_ACTIVATED
...
}
}
License key will be provided by our sales department.
From now on theMpfcEngine
instance is used for most use cases.
Adding to the layout
Add implementation 'com.google.android.material:material:x.y.z'
for back compatibility. Use FragmentActivity instead of a ComponentActivity successor to support our Fragment.
Jetpack Compose
In case of using Jetpack Compose, check Inter-op with XML inter-op docs by Google.
Insertion to the layout can be executed either by view or fragment. Our MapView
is basically a view containing MapFragment
.
MapView element
View plays the role of a wrapper around our MapFragment
. Once MapView
is inflated, you can access the inner fragment.
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
MapView(context).apply {
//do whatever you want, e.g.
//handle map controls visibility
val mapControls = this.mapFragment.mapControls
mapControls.setMapControlVisibility(
MapControls.MapControl.COMPASS,
true
)
//or add listener
this.mapFragment.addOnMapReadyListener {
}
}
},
update = {
}
)
Fragment element
You need to create an XML layout file in res/layout. e.g. fragment_navigation.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:name="com.mapfactor.sdk.map.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
and then use this layout to inflate in Kotlin like this.
AndroidViewBinding(FragmentNavigationBinding::inflate) {
val mapFragment = fragmentContainerView.getFragment<MapFragment>()
//do whatever you want, e.g.
//set night mode
mapFragment.setNightMode(true)
//handle map controls visibility
val mapControls = mapFragment.mapControls
mapControls.setMapControlVisibility(
MapControls.MapControl.COMPASS,
true
)
//or add listener
mapFragment.addOnMapReadyListener {
}
}
For more information, check official Google documentation.
View-based system
For layout implementation, there are two options - direct XML view containing MapFragment
on background or inserting a MapFragment
with FragmentContainerView.
MapView element
<com.mapfactor.sdk.map.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Fragment element
<androidx.fragment.app.FragmentContainerView
android:id="@+id/map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.mapfactor.sdk.map.MapFragment"/>
Data download
For downloading map, voice and sound data, use the downloadAppData
method of the AppDataManagerModule
.
MpfcEngine.getInstance().appDataManagerModule
.downloadAppData(dataIds, object : DataDownloadListener {
override fun onDownloadProgress(
dataId: String,
dataName: String,
iFile: Int,
numFiles: Int,
curFileProgress: Long,
curFileSize: Long,
totProgress: Long,
totSize: Long
) {
//process current progress
}
override fun onDownloadFinished() {
}
override fun onDownloadFailed(errorCode: AppDataManager.DownloadErrorCode) {
//handle error
}
override fun onEngineRestarted() {
}
})
TIP: If using Kotlin, you can take advantage of callbackFlow
.
Beware of executing methods related to MpfcEngine instance
repeatedly. You can call them again once onEngineRestarted
callback is invoked.