diff --git a/app/build.gradle b/app/build.gradle index 770be2ae..32d7f572 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,11 +66,8 @@ dependencies { implementation "androidx.appcompat:appcompat:$appCompat" implementation "androidx.legacy:legacy-support-v4:$supportLib" implementation "androidx.constraintlayout:constraintlayout:$constraintLayout" - implementation "androidx.core:core-ktx:$ktx" implementation "androidx.preference:preference:$preference" - - // architecture components implementation "androidx.navigation:navigation-fragment-ktx:$navigation" implementation "androidx.navigation:navigation-runtime-ktx:$navigation" implementation "androidx.navigation:navigation-ui-ktx:$navigation" @@ -78,24 +75,22 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle" - - // room implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-ktx:$room" kapt "androidx.room:room-compiler:$room" - // retrofit + implementation "com.google.dagger:dagger:$dagger" + kapt "com.google.dagger:dagger-compiler:$dagger" + implementation "com.squareup.retrofit2:retrofit:$retrofit" implementation "com.squareup.retrofit2:converter-gson:$retrofit" implementation "com.squareup.okhttp3:okhttp:$okhttp" - //dagger - implementation "com.google.dagger:dagger:$dagger" - kapt "com.google.dagger:dagger-compiler:$dagger" - - // predict4java - implementation "com.github.davidmoten:predict4java:$predict4java" - - // openStreetMaps implementation "org.osmdroid:osmdroid-android:$openStreetMap" + implementation "org.osmdroid:osmdroid-mapsforge:$openStreetMap" + implementation "org.mapsforge:mapsforge-map-android:$mapsForge" + implementation "org.mapsforge:mapsforge-map:$mapsForge" + implementation "org.mapsforge:mapsforge-themes:$mapsForge" + + implementation "com.github.davidmoten:predict4java:$predict4java" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bb75ea16..41288a85 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,8 @@ + + ): Boolean = + permissions.all { + ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED } - } - - override fun onRequestPermissionsResult(reqCode: Int, perms: Array, res: IntArray) { - when (reqCode) { - permLocationCode -> { - if (res.isNotEmpty() && res[0] == permGranted) { - viewModel.updatePosition() - } - } - } - } override fun onSupportNavigateUp(): Boolean { val navController = findNavController(R.id.nav_host) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapOsmFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapOsmFragment.kt index 21c8e0f6..00132a7a 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapOsmFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/fragments/MapOsmFragment.kt @@ -1,73 +1,208 @@ package com.rtbishop.look4sat.ui.fragments +import android.graphics.Color import android.os.Bundle +import android.os.Environment +import android.util.Log import android.view.View import androidx.fragment.app.Fragment -import androidx.preference.PreferenceManager +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import com.github.amsacode.predict4java.GroundStationPosition +import com.github.amsacode.predict4java.SatPos +import com.rtbishop.look4sat.Look4SatApp import com.rtbishop.look4sat.R +import com.rtbishop.look4sat.dagger.ViewModelFactory +import com.rtbishop.look4sat.data.Result +import com.rtbishop.look4sat.data.SatPass import com.rtbishop.look4sat.databinding.FragmentMapOsmBinding -import org.osmdroid.config.Configuration -import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import com.rtbishop.look4sat.ui.MainActivity +import com.rtbishop.look4sat.ui.SharedViewModel +import com.rtbishop.look4sat.utility.GeneralUtils +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.mapsforge.map.rendertheme.XmlRenderTheme +import org.mapsforge.map.rendertheme.XmlRenderThemeMenuCallback +import org.osmdroid.mapsforge.MapsForgeTileProvider +import org.osmdroid.mapsforge.MapsForgeTileSource +import org.osmdroid.tileprovider.util.SimpleRegisterReceiver import org.osmdroid.util.GeoPoint -import org.osmdroid.views.MapView -import org.osmdroid.views.overlay.OverlayItem +import org.osmdroid.views.overlay.Marker +import org.osmdroid.views.overlay.Polygon +import org.osmdroid.views.overlay.Polyline +import org.osmdroid.views.overlay.compass.CompassOverlay +import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider +import java.io.File +import java.io.InputStream +import java.util.* +import javax.inject.Inject class MapOsmFragment : Fragment(R.layout.fragment_map_osm) { + @Inject + lateinit var modelFactory: ViewModelFactory + private lateinit var mainActivity: MainActivity + private lateinit var viewModel: SharedViewModel private lateinit var binding: FragmentMapOsmBinding - private lateinit var mapView: MapView + private var satPassList = emptyList() + private var gsp = GroundStationPosition(0.0, 0.0, 0.0) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - - val appContext = requireActivity().applicationContext - binding = FragmentMapOsmBinding.bind(view) - binding.mapView.apply { - controller.animateTo(mapCenter) - controller.setZoom(2.5) - setMultiTouchControls(true) - maxZoomLevel = 7.5 - minZoomLevel = 2.5 -// isClickable = true -// setScrollableAreaLimitLatitude(-90.0, 90.0, 0) -// setScrollableAreaLimitLongitude(-180.0, 180.0, 0) - } + mainActivity = requireActivity() as MainActivity + (mainActivity.application as Look4SatApp).appComponent.inject(this) + viewModel = ViewModelProvider(mainActivity, modelFactory).get(SharedViewModel::class.java) - Configuration - .getInstance() - .load(appContext, PreferenceManager.getDefaultSharedPreferences(appContext)) - - init() + setupObservers() } - private fun init() { - mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE) - val gPt = GeoPoint(28.6337874, 77.35767599999997) - val gPt2 = GeoPoint(28.638472, 77.360667) - mapView.controller.setCenter(gPt) + private fun setupObservers() { + viewModel.getGSP().observe(viewLifecycleOwner, Observer { result -> + when (result) { + is Result.Success -> gsp = result.data + } + }) - /*place icon on map*/ - val items = ArrayList() - items.add(OverlayItem("Current Location", "Amrapali Village, Indirapuram", gPt)) - items.add(OverlayItem("Destination", "Aditya Mall, Indirapuram", gPt2)) + viewModel.getPassList().observe(viewLifecycleOwner, Observer { result -> + when (result) { + is Result.Success -> { + satPassList = result.data + setupMapWithAdapter() + } + } + }) + } + + inner class MyRenderTheme : XmlRenderTheme { + + override fun getRenderThemeAsStream(): InputStream { + return resources.openRawResource(R.raw.customrender) + } + + override fun getMenuCallback(): XmlRenderThemeMenuCallback? { + return null + } + + override fun getRelativePathPrefix(): String { + return "" + } + + override fun setMenuCallback(menuCallback: XmlRenderThemeMenuCallback) {} + + } + + private fun setupMapWithAdapter() { + val mapsArray = arrayOf(File(Environment.getExternalStorageDirectory(), "world.map")) + val tileSource = MapsForgeTileSource.createFromFiles(mapsArray, MyRenderTheme(), null) + val registerReceiver = SimpleRegisterReceiver(mainActivity.applicationContext) + val tileProvider = MapsForgeTileProvider(registerReceiver, tileSource, null) + + binding.mapView.tileProvider = tileProvider + + binding.mapView.apply { + overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT + overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT + minZoomLevel = 3.00 + maxZoomLevel = 8.00 + controller.setZoom(5.0) + + val startPoint = GeoPoint(gsp.latitude, gsp.longitude) + controller.setCenter(startPoint) + + val startMarker = Marker(binding.mapView) + startMarker.position = startPoint + startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + startMarker.title = "Ground Station Position" + overlays.add(startMarker) + + var dateNow = Date(System.currentTimeMillis()) + val selectedSat = satPassList[3] + val orbitalPeriod = (24 * 60 / selectedSat.tle.meanmo).toInt() + var positions = selectedSat.predictor.getPositions(dateNow, 60, 0, orbitalPeriod * 3) + + drawGroundTrack(positions) + Log.d("myTag", selectedSat.tle.name) + + val compassOverlay = CompassOverlay( + context, + InternalCompassOrientationProvider(context), + binding.mapView + ) + compassOverlay.enableCompass() + overlays.add(compassOverlay) + + setMultiTouchControls(true) + setScrollableAreaLimitLatitude(85.0, -85.0, 0) + + lifecycleScope.launch { + while (true) { + delay(3000) + dateNow = Date(System.currentTimeMillis()) + positions = + selectedSat.predictor.getPositions(dateNow, 60, 0, orbitalPeriod * 3) + drawPosition(GeoPoint(positions[0].latitude, positions[0].longitude)) + binding.mapView.invalidate() + } + } + } + } + + private fun drawPosition(position: GeoPoint) { + val satPosition = Polygon(binding.mapView) + val trackPoints = mutableListOf() + + Log.d("myTag", "${position.latitude}, ${position.longitude}") + + val lat = GeneralUtils.rad2Deg(position.latitude) + var lon = GeneralUtils.rad2Deg(position.longitude) + if (lon > 180.0) lon -= 360.0 + trackPoints.add(GeoPoint(lat, lon)) + + val startMarker = Marker(binding.mapView) + startMarker.position = GeoPoint(lat, lon) + startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) + startMarker.title = "Sat Position" + binding.mapView.overlays.add(startMarker) + + Log.d("myTag", "$lat, $lon") + + binding.mapView.overlays.add(satPosition) + satPosition.points = trackPoints + binding.mapView.invalidate() + } + + private fun drawGroundTrack(list: List) { + val groundTrack = Polyline(binding.mapView) + val trackPoints = mutableListOf() + var lat = 0.0 + var lon = 0.0 + + Log.d("myTag", "${list[1].latitude}, ${list[1].longitude}") + + list.forEach { + lat = GeneralUtils.rad2Deg(it.latitude) * -1 + lon = GeneralUtils.rad2Deg(it.longitude) + if (lon > 180.0) lon -= 360.0 + trackPoints.add(GeoPoint(lat, lon)) + } + + Log.d("myTag", "$lat, $lon") + + groundTrack.setPoints(trackPoints) + groundTrack.setDensityMultiplier(0.5f) + binding.mapView.overlays.add(groundTrack) + binding.mapView.invalidate() } override fun onResume() { super.onResume() - //this will refresh the osmdroid configuration on resuming. - //if you make changes to the configuration, use - //SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - //Configuration.getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this)); - mapView.onResume() //needed for compass, my location overlays, v6.0.0 and up + binding.mapView.onResume() } override fun onPause() { super.onPause() - //this will refresh the osmdroid configuration on resuming. - //if you make changes to the configuration, use - //SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - //Configuration.getInstance().save(this, prefs); - mapView.onPause() //needed for compass, my location overlays, v6.0.0 and up + binding.mapView.onPause() } } \ No newline at end of file diff --git a/app/src/main/res/raw/customrender.xml b/app/src/main/res/raw/customrender.xml new file mode 100644 index 00000000..9c939634 --- /dev/null +++ b/app/src/main/res/raw/customrender.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/raw/world.map b/app/src/main/res/raw/world.map new file mode 100644 index 00000000..03f9fd2a Binary files /dev/null and b/app/src/main/res/raw/world.map differ diff --git a/build.gradle b/build.gradle index af5954e1..3e2964cd 100644 --- a/build.gradle +++ b/build.gradle @@ -48,21 +48,19 @@ ext { appCompat = '1.1.0' supportLib = '1.0.0' constraintLayout = '1.1.3' - ktx = '1.3.0' preference = '1.1.1' - navigation = '2.2.2' lifecycle = '2.2.0' - room = '2.2.5' + dagger = '2.28' + retrofit = '2.9.0' okhttp = '4.7.2' - dagger = '2.28' + openStreetMap = '6.1.6' + mapsForge = '0.13.0' predict4java = '1.3.1' - - openStreetMap = '6.1.6' }