Rebased from master

This commit is contained in:
Arty Bishop committed 2020-09-19 20:19:25 +01:00
1 parent 770fb9b244
commit e90322d828
8 files changed
+229 -89

No files matched your search

+9 -14
View File
@@ -66,11 +66,8 @@ dependencies {
implementation "androidx.appcompat:appcompat:$appCompat" implementation "androidx.appcompat:appcompat:$appCompat"
implementation "androidx.legacy:legacy-support-v4:$supportLib" implementation "androidx.legacy:legacy-support-v4:$supportLib"
implementation "androidx.constraintlayout:constraintlayout:$constraintLayout" implementation "androidx.constraintlayout:constraintlayout:$constraintLayout"
implementation "androidx.core:core-ktx:$ktx" implementation "androidx.core:core-ktx:$ktx"
implementation "androidx.preference:preference:$preference" implementation "androidx.preference:preference:$preference"
// architecture components
implementation "androidx.navigation:navigation-fragment-ktx:$navigation" implementation "androidx.navigation:navigation-fragment-ktx:$navigation"
implementation "androidx.navigation:navigation-runtime-ktx:$navigation" implementation "androidx.navigation:navigation-runtime-ktx:$navigation"
implementation "androidx.navigation:navigation-ui-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-viewmodel-ktx:$lifecycle"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle"
// room
implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room" implementation "androidx.room:room-ktx:$room"
kapt "androidx.room:room-compiler:$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:retrofit:$retrofit"
implementation "com.squareup.retrofit2:converter-gson:$retrofit" implementation "com.squareup.retrofit2:converter-gson:$retrofit"
implementation "com.squareup.okhttp3:okhttp:$okhttp" 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-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"
} }
+2
View File
@@ -24,6 +24,8 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application
android:name="com.rtbishop.look4sat.Look4SatApp" android:name="com.rtbishop.look4sat.Look4SatApp"
@@ -22,6 +22,7 @@ package com.rtbishop.look4sat.dagger
import android.content.Context import android.content.Context
import com.rtbishop.look4sat.dagger.modules.* import com.rtbishop.look4sat.dagger.modules.*
import com.rtbishop.look4sat.ui.MainActivity import com.rtbishop.look4sat.ui.MainActivity
import com.rtbishop.look4sat.ui.fragments.MapOsmFragment
import com.rtbishop.look4sat.ui.fragments.MapViewFragment import com.rtbishop.look4sat.ui.fragments.MapViewFragment
import com.rtbishop.look4sat.ui.fragments.PassListFragment import com.rtbishop.look4sat.ui.fragments.PassListFragment
import com.rtbishop.look4sat.ui.fragments.PolarViewFragment import com.rtbishop.look4sat.ui.fragments.PolarViewFragment
@@ -45,4 +46,5 @@ interface AppComponent {
fun inject(mapViewFragment: MapViewFragment) fun inject(mapViewFragment: MapViewFragment)
fun inject(passListFragment: PassListFragment) fun inject(passListFragment: PassListFragment)
fun inject(polarViewFragment: PolarViewFragment) fun inject(polarViewFragment: PolarViewFragment)
fun inject(mapOsmFragment: MapOsmFragment)
} }
@@ -21,6 +21,7 @@ package com.rtbishop.look4sat.ui
import android.Manifest import android.Manifest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
@@ -30,7 +31,6 @@ import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -54,10 +54,13 @@ import javax.inject.Inject
class MainActivity : AppCompatActivity(), TleSourcesDialogFragment.SourcesSubmitListener { class MainActivity : AppCompatActivity(), TleSourcesDialogFragment.SourcesSubmitListener {
private val pickFileReqCode = 111 private val pickFileReqCode = 1001
private val permLocationCode = 101 private val permissionsReqCode = 1000
private val permLocation = Manifest.permission.ACCESS_FINE_LOCATION private val permissions = arrayOf(
private val permGranted = PackageManager.PERMISSION_GRANTED Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
@Inject @Inject
lateinit var viewModelFactory: ViewModelFactory lateinit var viewModelFactory: ViewModelFactory
@@ -83,6 +86,10 @@ class MainActivity : AppCompatActivity(), TleSourcesDialogFragment.SourcesSubmit
setupDrawer() setupDrawer()
viewModel.setDefaultTleSources() viewModel.setDefaultTleSources()
if (!hasPermissions(this, permissions)) {
ActivityCompat.requestPermissions(this, permissions, permissionsReqCode)
}
} }
@SuppressLint("SourceLockedOrientationActivity") @SuppressLint("SourceLockedOrientationActivity")
@@ -154,7 +161,7 @@ class MainActivity : AppCompatActivity(), TleSourcesDialogFragment.SourcesSubmit
private fun setupDrawer() { private fun setupDrawer() {
drawerBinding.drawerBtnLoc.setOnClickListener { drawerBinding.drawerBtnLoc.setOnClickListener {
requestLocationUpdate() viewModel.updatePosition()
it.lockButton() it.lockButton()
} }
drawerBinding.drawerBtnTleFile.setOnClickListener { drawerBinding.drawerBtnTleFile.setOnClickListener {
@@ -193,27 +200,10 @@ class MainActivity : AppCompatActivity(), TleSourcesDialogFragment.SourcesSubmit
} }
} }
private fun requestLocationUpdate() { private fun hasPermissions(context: Context, permissions: Array<String>): Boolean =
if (ContextCompat.checkSelfPermission(this, permLocation) != permGranted) { permissions.all {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permLocation)) { ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
getString(R.string.err_no_permissions).toast(this)
} else {
ActivityCompat.requestPermissions(this, arrayOf(permLocation), permLocationCode)
}
} else {
viewModel.updatePosition()
} }
}
override fun onRequestPermissionsResult(reqCode: Int, perms: Array<out String>, res: IntArray) {
when (reqCode) {
permLocationCode -> {
if (res.isNotEmpty() && res[0] == permGranted) {
viewModel.updatePosition()
}
}
}
}
override fun onSupportNavigateUp(): Boolean { override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host) val navController = findNavController(R.id.nav_host)
@@ -1,73 +1,208 @@
package com.rtbishop.look4sat.ui.fragments package com.rtbishop.look4sat.ui.fragments
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View import android.view.View
import androidx.fragment.app.Fragment 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.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 com.rtbishop.look4sat.databinding.FragmentMapOsmBinding
import org.osmdroid.config.Configuration import com.rtbishop.look4sat.ui.MainActivity
import org.osmdroid.tileprovider.tilesource.TileSourceFactory 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.util.GeoPoint
import org.osmdroid.views.MapView import org.osmdroid.views.overlay.Marker
import org.osmdroid.views.overlay.OverlayItem 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) { 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 binding: FragmentMapOsmBinding
private lateinit var mapView: MapView private var satPassList = emptyList<SatPass>()
private var gsp = GroundStationPosition(0.0, 0.0, 0.0)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val appContext = requireActivity().applicationContext
binding = FragmentMapOsmBinding.bind(view) binding = FragmentMapOsmBinding.bind(view)
binding.mapView.apply { mainActivity = requireActivity() as MainActivity
controller.animateTo(mapCenter) (mainActivity.application as Look4SatApp).appComponent.inject(this)
controller.setZoom(2.5) viewModel = ViewModelProvider(mainActivity, modelFactory).get(SharedViewModel::class.java)
setMultiTouchControls(true)
maxZoomLevel = 7.5
minZoomLevel = 2.5
// isClickable = true
// setScrollableAreaLimitLatitude(-90.0, 90.0, 0)
// setScrollableAreaLimitLongitude(-180.0, 180.0, 0)
}
Configuration setupObservers()
.getInstance()
.load(appContext, PreferenceManager.getDefaultSharedPreferences(appContext))
init()
} }
private fun init() { private fun setupObservers() {
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE) viewModel.getGSP().observe(viewLifecycleOwner, Observer { result ->
val gPt = GeoPoint(28.6337874, 77.35767599999997) when (result) {
val gPt2 = GeoPoint(28.638472, 77.360667) is Result.Success -> gsp = result.data
mapView.controller.setCenter(gPt) }
})
/*place icon on map*/ viewModel.getPassList().observe(viewLifecycleOwner, Observer { result ->
val items = ArrayList<OverlayItem>() when (result) {
items.add(OverlayItem("Current Location", "Amrapali Village, Indirapuram", gPt)) is Result.Success -> {
items.add(OverlayItem("Destination", "Aditya Mall, Indirapuram", gPt2)) 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<GeoPoint>()
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<SatPos>) {
val groundTrack = Polyline(binding.mapView)
val trackPoints = mutableListOf<GeoPoint>()
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() { override fun onResume() {
super.onResume() super.onResume()
//this will refresh the osmdroid configuration on resuming. binding.mapView.onResume()
//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
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
//this will refresh the osmdroid configuration on resuming. binding.mapView.onPause()
//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
} }
} }
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<rendertheme version="5">
<rule
e="way"
k="natural"
v="issea|sea">
<area fill="#242424" />
</rule>
<rule
e="way"
k="natural"
v="nosea">
<area fill="#606060" />
</rule>
</rendertheme>
Binary file not shown.
+4 -6
View File
@@ -48,21 +48,19 @@ ext {
appCompat = '1.1.0' appCompat = '1.1.0'
supportLib = '1.0.0' supportLib = '1.0.0'
constraintLayout = '1.1.3' constraintLayout = '1.1.3'
ktx = '1.3.0' ktx = '1.3.0'
preference = '1.1.1' preference = '1.1.1'
navigation = '2.2.2' navigation = '2.2.2'
lifecycle = '2.2.0' lifecycle = '2.2.0'
room = '2.2.5' room = '2.2.5'
dagger = '2.28'
retrofit = '2.9.0' retrofit = '2.9.0'
okhttp = '4.7.2' okhttp = '4.7.2'
dagger = '2.28' openStreetMap = '6.1.6'
mapsForge = '0.13.0'
predict4java = '1.3.1' predict4java = '1.3.1'
openStreetMap = '6.1.6'
} }