I have recently started studying android and kotlin programming, I'm trying to create an application that allows you to create one or more routes on a map, save it and then retrieve it when necessary. I chose to use osmDroid and osmBonusPack because open source but I don't find much documentation online, I'm trying to visualize a path between two Markers, I was able to visualize two markers and draw a straight line between two other points, now I'm trying to make the path but I don't understand how to proceed. Following the tutorial:
https://github.com/MKergall/osmbonuspack/wiki/Tutorial_1
trying to put some println("check") i understand that the app crashes when it gets to the line:
val road: Road = roadManager.getRoad(waypoints)
what's my problem? what is the error:
E/AndroidRuntime: FATAL EXCEPTION: main Process: uk.co.lorenzopulcinelli.trackapp, PID: 28815 java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/Request$Builder;
?
package uk.co.lorenzopulcinelli.trackapp
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.DisplayMetrics
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.preference.PreferenceManager
import org.osmdroid.api.IMapController
import org.osmdroid.bonuspack.routing.OSRMRoadManager
import org.osmdroid.bonuspack.routing.Road
import org.osmdroid.bonuspack.routing.RoadManager
import org.osmdroid.config.Configuration
import org.osmdroid.config.Configuration.*
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
import org.osmdroid.views.overlay.*
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay
import org.osmdroid.views.overlay.Marker
class MainActivity : AppCompatActivity() {
private lateinit var mapView : MapView
private lateinit var myLocationNewOverlay: MyLocationNewOverlay
private lateinit var compassOverlay: CompassOverlay
private lateinit var mapController: IMapController
private lateinit var userAgent: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermission()
getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this))
setContentView(R.layout.activity_main)
mapView = findViewById<MapView>(R.id.map)
mapView.setTileSource(TileSourceFactory.MAPNIK)
mapView.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
mapController = mapView.controller
myLocationNewOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mapView)
myLocationNewOverlay.enableMyLocation()
myLocationNewOverlay.enableMyLocation()
myLocationNewOverlay.isDrawAccuracyEnabled = true
myLocationNewOverlay.runOnFirstFix { runOnUiThread {
mapController.animateTo(myLocationNewOverlay.myLocation)
mapController.setZoom(9.5)
}
}
mapView.overlays.add(myLocationNewOverlay)
Configuration.getInstance().userAgentValue = "lolloMaps"
println(myLocationNewOverlay.myLocation)
println("creato")
compassOverlay = CompassOverlay(this, InternalCompassOrientationProvider(this), mapView)
compassOverlay.enableCompass()
mapView.overlays.add(compassOverlay)
// val overlay = LatLonGridlineOverlay2()
// mapView.overlays.add(overlay)
val rotationGestureOverlay = RotationGestureOverlay(mapView)
rotationGestureOverlay.isEnabled
mapView.setMultiTouchControls(true)
mapView.overlays.add(rotationGestureOverlay)
myLocationNewOverlay = MyLocationNewOverlay(GpsMyLocationProvider(this), mapView)
myLocationNewOverlay.enableMyLocation()
mapView.overlays.add(myLocationNewOverlay)
val dm : DisplayMetrics = resources.displayMetrics
val scaleBarOverlay = ScaleBarOverlay(mapView)
scaleBarOverlay.setCentred(true)
scaleBarOverlay.setScaleBarOffset(dm.widthPixels / 2, 10)
mapView.overlays.add(scaleBarOverlay)
mioMarker(55.45, 22.48, 1)
mioMarker(47.22, 15.48, 2)
val pnt1: GeoPoint = GeoPoint(52.50, 13.40)
val pnt2: GeoPoint = GeoPoint(42.54, 27.40)
val polyline: Polyline = Polyline(mapView)
polyline.addPoint(pnt1)
polyline.addPoint(pnt2)
mapView.overlays.add(polyline)
mapView.invalidate()
val roadManager:RoadManager = OSRMRoadManager(this, )
val waypoints = ArrayList<GeoPoint>()
val startPoint: GeoPoint = GeoPoint(66.7, -14.6)
waypoints.add(startPoint)
val endPoint: GeoPoint = GeoPoint(48.4, -1.9)
waypoints.add(endPoint)
val road: Road = roadManager.getRoad(waypoints)
val roadOverlay: Polyline = RoadManager.buildRoadOverlay(road)
mapView.overlays.add(roadOverlay)
mapView.invalidate()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
super.onPause()
mapView.onPause()
}
private fun hasPermission() : Boolean {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
private fun requestPermission() {
val permission = mutableListOf<String>()
if (!hasPermission()) {
permission.add(Manifest.permission.ACCESS_FINE_LOCATION)
}
if (permission.isNotEmpty()) {
ActivityCompat.requestPermissions(this, permission.toTypedArray(), 0)
}
}
// fun add Marker
private fun mioMarker(lati: Double, longi: Double, i: Int) {
val pinMarker = Marker(mapView)
val geoPoint = GeoPoint(lati, longi)
pinMarker.position = geoPoint
pinMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
pinMarker.title = "Title"
pinMarker.subDescription = "i'm pin #$i, my coordinate $lati, $longi."
pinMarker.isDraggable = true
mapView.overlays.add(pinMarker)
mapView.invalidate()
}
}
this is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="uk.co.lorenzopulcinelli.trackapp">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TrackApp"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and this is my buil.gradle:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "uk.co.lorenzopulcinelli.trackapp"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.preference:preference:1.2.0' //aggiunta per utilizzare import androidx.preference.PreferenceManager
implementation 'com.google.android.gms:play-services-location:20.0.0' //aggiunta per richiedere permessi localizzazione
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation files('/home/acer/AndroidStudioProjects/TrackApp/app/libs/osmbonuspack_6.9.0.aar')
implementation files('/home/acer/AndroidStudioProjects/TrackApp/app/libs/osmdroid-android-6.1.13.aar')
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
below my Logcat:
07/01 17:42:05: Launching 'app' on Xiaomi Redmi Note 7.
Install successfully finished in 4 s 662 ms.
$ adb shell am start -n "uk.co.lorenzopulcinelli.trackapp/uk.co.lorenzopulcinelli.trackapp.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 28815 on device 'xiaomi-redmi_note_7-16dccaa4'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/Perf: Connecting to perf service.
I/FeatureParser: can't find lavender.xml in assets/device_features/,it may be in /system/etc/device_features
E/libc: Access denied finding property "ro.vendor.df.effect.conflict"
W/inelli.trackapp: type=1400 audit(0.0:93235): avc: denied { read } for name="u:object_r:vendor_displayfeature_prop:s0" dev="tmpfs" ino=17716 scontext=u:r:untrusted_app:s0:c168,c257,c512,c768 tcontext=u:object_r:vendor_displayfeature_prop:s0 tclass=file permissive=0
E/Perf: Fail to get file list uk.co.lorenzopulcinelli.trackapp
E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
I/StorageUtils: /data/user/0/uk.co.lorenzopulcinelli.trackapp/files is writable
I/StorageUtils: /storage/emulated/0/Android/data/uk.co.lorenzopulcinelli.trackapp/files is writable
I/StorageUtils: /storage/4A6A-676E/Android/data/uk.co.lorenzopulcinelli.trackapp/files is writable
I/StorageUtils: /data/user/0/uk.co.lorenzopulcinelli.trackapp/files is writable
I/StorageUtils: /storage/emulated/0/Android/data/uk.co.lorenzopulcinelli.trackapp/files is writable
I/StorageUtils: /storage/4A6A-676E/Android/data/uk.co.lorenzopulcinelli.trackapp/files is writable
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
W/inelli.trackap: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/inelli.trackap: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
I/OsmDroid: Using tile source specified in layout attributes: Mapnik
I/OsmDroid: Using tile source: Mapnik
I/OsmDroid: Tile cache increased from 0 to 9
I/System.out: null
I/System.out: creato
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
I/chatty: uid=10424(uk.co.lorenzopulcinelli.trackapp) identical 5 lines
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
I/chatty: uid=10424(uk.co.lorenzopulcinelli.trackapp) identical 6 lines
D/ForceDarkHelper: updateByCheckExcludeList: pkg: uk.co.lorenzopulcinelli.trackapp activity: uk.co.lorenzopulcinelli.trackapp.MainActivity@148f695
I/System.out: inizio
I/System.out: passo1 - creoArrayList
I/System.out: passo2 - CreoPuntiEAggiungoInArrayList
I/System.out: passo3 - CreoStrada
D/BONUSPACK: OSRMRoadManager.getRoads:https://routing.openstreetmap.de/routed-car/route/v1/driving/-14.6000000000,66.7000000000;-1.9000000000,48.4000000000?alternatives=false&overview=full&steps=true
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: uk.co.lorenzopulcinelli.trackapp, PID: 28815
java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/Request$Builder;
at org.osmdroid.bonuspack.utils.HttpConnection.doGet(HttpConnection.java:65)
at org.osmdroid.bonuspack.utils.BonusPackHelper.requestStringFromUrl(BonusPackHelper.java:59)
at org.osmdroid.bonuspack.routing.OSRMRoadManager.getRoads(OSRMRoadManager.java:194)
at org.osmdroid.bonuspack.routing.OSRMRoadManager.getRoad(OSRMRoadManager.java:286)
at uk.co.lorenzopulcinelli.trackapp.MainActivity.onCreate(MainActivity.kt:132)
at android.app.Activity.performCreate(Activity.java:7893)
at android.app.Activity.performCreate(Activity.java:7880)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3286)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3460)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.Request$Builder" on path: DexPathList[[zip file "/data/app/uk.co.lorenzopulcinelli.trackapp-jx1_0YR4HzgrzlHgIcGy8w==/base.apk"],nativeLibraryDirectories=[/data/app/uk.co.lorenzopulcinelli.trackapp-jx1_0YR4HzgrzlHgIcGy8w==/lib/arm64, /system/lib64, /system/product/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:230)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at org.osmdroid.bonuspack.utils.HttpConnection.doGet(HttpConnection.java:65)
at org.osmdroid.bonuspack.utils.BonusPackHelper.requestStringFromUrl(BonusPackHelper.java:59)
at org.osmdroid.bonuspack.routing.OSRMRoadManager.getRoads(OSRMRoadManager.java:194)
at org.osmdroid.bonuspack.routing.OSRMRoadManager.getRoad(OSRMRoadManager.java:286)
at uk.co.lorenzopulcinelli.trackapp.MainActivity.onCreate(MainActivity.kt:132)
at android.app.Activity.performCreate(Activity.java:7893)
at android.app.Activity.performCreate(Activity.java:7880)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3286)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3460)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
I/Process: Sending signal. PID: 28815 SIG: 9
I found the solution by importing dependencies that I had overlooked I followed the answer to this question:
Unable to resolve dependency for retrofit2
in particular it was enough to add these dependencies, these in my app build.gradle file:
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
and these in my project build.gradle file:
allprojects {
repositories {
google()
maven { url "https://jitpack.io" }
jcenter()
}
}