Moved the code from activity to ViewModel. Minor layout updates.

This commit is contained in:
Arty Bishop committed 2019-10-30 23:20:16 +00:00
1 parent be20786a18
commit dc62d660a8
7 files changed
+124 -137

No files matched your search

@@ -1,9 +1,7 @@
package com.rtbishop.lookingsat.repo package com.rtbishop.lookingsat.repo
import android.util.Log
import com.rtbishop.lookingsat.api.RemoteDataSource import com.rtbishop.lookingsat.api.RemoteDataSource
import com.rtbishop.lookingsat.db.LocalDataSource import com.rtbishop.lookingsat.db.LocalDataSource
import java.io.IOException
import java.io.InputStream import java.io.InputStream
class Repository( class Repository(
@@ -15,11 +13,7 @@ class Repository(
} }
suspend fun updateTransmittersDatabase() { suspend fun updateTransmittersDatabase() {
try { localSource.insertTransmitters(remoteSource.fetchTransmittersList())
localSource.insertTransmitters(remoteSource.fetchTransmittersList())
} catch (exception: IOException) {
Log.d(this.javaClass.simpleName, exception.toString())
}
} }
suspend fun getTransmittersForSat(id: Int): List<Transmitter> { suspend fun getTransmittersForSat(id: Int): List<Transmitter> {
@@ -2,10 +2,8 @@ package com.rtbishop.lookingsat.ui
import android.Manifest import android.Manifest
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.location.Location
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer import android.os.CountDownTimer
@@ -21,7 +19,6 @@ import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.navigation.findNavController import androidx.navigation.findNavController
@@ -29,28 +26,23 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import com.rtbishop.lookingsat.R import com.rtbishop.lookingsat.R
import com.rtbishop.lookingsat.vm.MainViewModel import com.rtbishop.lookingsat.vm.MainViewModel
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
const val LOCATION_REQ = 101
const val LOCATION_PERM = Manifest.permission.ACCESS_FINE_LOCATION
const val GRANTED = PackageManager.PERMISSION_GRANTED
const val GITHUB_URL = "https://github.com/rt-bishop/LookingSat"
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private val permLocationCode = 101
private val permLocation = Manifest.permission.ACCESS_FINE_LOCATION
private val permGranted = PackageManager.PERMISSION_GRANTED
private val githubUrl = "https://github.com/rt-bishop/LookingSat"
private lateinit var appBarConfig: AppBarConfiguration private lateinit var appBarConfig: AppBarConfiguration
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var timerLayout: ConstraintLayout private lateinit var timerLayout: ConstraintLayout
private lateinit var timeToAos: TextView private lateinit var timeToAos: TextView
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var preferences: SharedPreferences
private lateinit var drawerLat: TextView private lateinit var drawerLat: TextView
private lateinit var drawerLon: TextView private lateinit var drawerLon: TextView
private lateinit var drawerHeight: TextView private lateinit var drawerHeight: TextView
@@ -61,39 +53,31 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setupComponents() setupComponents()
setupNavigation() setupDrawer()
setupTimer() setupTimer()
updateDrawerValues() updateLocation()
} }
private fun setupComponents() { private fun setupComponents() {
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java) viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
preferences = PreferenceManager.getDefaultSharedPreferences(this)
timerLayout = findViewById(R.id.timer_layout) timerLayout = findViewById(R.id.timer_layout)
timeToAos = findViewById(R.id.time_to_aos) timeToAos = findViewById(R.id.time_to_aos)
}
private fun setupNavigation() {
val toolbar: Toolbar = findViewById(R.id.toolbar) val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout) val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view) val navView: NavigationView = findViewById(R.id.nav_view)
val header = navView.getHeaderView(0) val header = navView.getHeaderView(0)
drawerLat = header.findViewById(R.id.drawer_lat_value) drawerLat = header.findViewById(R.id.drawer_lat_value)
drawerLon = header.findViewById(R.id.drawer_lon_value) drawerLon = header.findViewById(R.id.drawer_lon_value)
drawerHeight = header.findViewById(R.id.drawer_height_value) drawerHeight = header.findViewById(R.id.drawer_height_value)
drawerSubTitle = header.findViewById(R.id.drawer_link) drawerSubTitle = header.findViewById(R.id.drawer_link)
drawerGetLocation = header.findViewById(R.id.drawer_get_location) drawerGetLocation = header.findViewById(R.id.drawer_get_location)
val navController = findNavController(R.id.nav_host)
appBarConfig = AppBarConfiguration( val navController = findNavController(R.id.nav_host)
setOf( appBarConfig = AppBarConfiguration(setOf(R.id.nav_sky, R.id.nav_single_sat), drawerLayout)
R.id.nav_sky,
R.id.nav_single_sat
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfig) setupActionBarWithNavController(navController, appBarConfig)
navView.setupWithNavController(navController) navView.setupWithNavController(navController)
@@ -113,22 +97,23 @@ class MainActivity : AppCompatActivity() {
} }
} }
} }
}
drawerSubTitle.setOnClickListener { private fun setupDrawer() {
openGitHub() drawerSubTitle.setOnClickListener { goToGithub() }
}
drawerGetLocation.startAnimation( drawerGetLocation.startAnimation(AnimationUtils.loadAnimation(this, R.anim.pulse))
AnimationUtils.loadAnimation(
this,
R.anim.pulse
)
)
drawerGetLocation.setOnClickListener { drawerGetLocation.setOnClickListener {
it.isEnabled = false it.isEnabled = false
updateLocation() updateLocation()
it.postDelayed({ it.isEnabled = true }, 3600) it.postDelayed({ it.isEnabled = true }, 3600)
} }
viewModel.gsp.observe(this, androidx.lifecycle.Observer { gsp ->
drawerLat.text = String.format("%.4f", gsp.latitude)
drawerLon.text = String.format("%.4f", gsp.longitude)
drawerHeight.text = String.format("%.1fm", gsp.heightAMSL)
})
} }
private fun setupTimer() { private fun setupTimer() {
@@ -158,69 +143,31 @@ class MainActivity : AppCompatActivity() {
} }
private fun updateLocation() { private fun updateLocation() {
if (ContextCompat.checkSelfPermission( if (ContextCompat.checkSelfPermission(this, permLocation) != permGranted) {
this, if (ActivityCompat.shouldShowRequestPermissionRationale(this, permLocation)) {
LOCATION_PERM
) != GRANTED
) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
LOCATION_PERM
)
) {
Toast.makeText(this, "Missing permissions", Toast.LENGTH_LONG).show() Toast.makeText(this, "Missing permissions", Toast.LENGTH_LONG).show()
} else { } else {
ActivityCompat.requestPermissions( ActivityCompat.requestPermissions(this, arrayOf(permLocation), permLocationCode)
this, arrayOf(LOCATION_PERM),
LOCATION_REQ
)
} }
} else { } else {
getPreciseLocation() viewModel.updateLocation()
} }
} }
private fun getPreciseLocation() { private fun goToGithub() {
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> val intentGitHub = Intent(Intent.ACTION_VIEW, Uri.parse(githubUrl))
val lat = location?.latitude ?: 51.5074
val lon = location?.longitude ?: 0.1278
val height = location?.altitude ?: 48.0
preferences.edit {
putDouble("LATITUDE", lat)
putDouble("LONGITUDE", lon)
putDouble("HEIGHT", height)
apply()
}
updateDrawerValues()
Toast.makeText(this, "Location was set", Toast.LENGTH_SHORT).show()
}
}
private fun updateDrawerValues() {
val lat = preferences.getDouble("LATITUDE", 51.5074)
val lon = preferences.getDouble("LONGITUDE", 0.1278)
val height = preferences.getDouble("HEIGHT", 48.0)
drawerLat.text = String.format("%.4f", lat)
drawerLon.text = String.format("%.4f", lon)
drawerHeight.text = String.format("%.1fm", height)
}
private fun openGitHub() {
val intentGitHub = Intent(Intent.ACTION_VIEW, Uri.parse(GITHUB_URL))
startActivity(intentGitHub) startActivity(intentGitHub)
} }
override fun onRequestPermissionsResult( private fun exit() {
requestCode: Int, finish()
permissions: Array<out String>, }
grantResults: IntArray
) { override fun onRequestPermissionsResult(reqCode: Int, perms: Array<out String>, res: IntArray) {
when (requestCode) { when (reqCode) {
LOCATION_REQ -> { permLocationCode -> {
if (grantResults.isNotEmpty() && grantResults[0] == GRANTED) { if (res.isNotEmpty() && res[0] == permGranted) {
getPreciseLocation() viewModel.updateLocation()
} }
} }
} }
@@ -238,19 +185,8 @@ class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.fetch_trans -> Toast.makeText(this, "Fetch transmit", Toast.LENGTH_SHORT).show() R.id.menu_refresh -> Toast.makeText(this, "Refresh", Toast.LENGTH_SHORT).show()
R.id.save_to_db -> Toast.makeText(this, "Saving to DB", Toast.LENGTH_SHORT).show()
R.id.load_from_db -> Toast.makeText(this, "Loading from DB", Toast.LENGTH_SHORT).show()
R.id.fetch_tle -> Toast.makeText(this, "Fetching TLE", Toast.LENGTH_SHORT).show()
R.id.load_tle -> Toast.makeText(this, "Loading TLE", Toast.LENGTH_SHORT).show()
R.id.action_exit -> finish()
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
} }
fun SharedPreferences.Editor.putDouble(key: String, double: Double): SharedPreferences.Editor =
putLong(key, java.lang.Double.doubleToRawLongBits(double))
fun SharedPreferences.getDouble(key: String, default: Double) =
java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))
@@ -1,11 +1,76 @@
package com.rtbishop.lookingsat.vm package com.rtbishop.lookingsat.vm
import android.app.Application import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import android.location.Location
import android.widget.Toast
import androidx.core.content.edit
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import com.github.amsacode.predict4java.GroundStationPosition
import com.google.android.gms.location.LocationServices
import com.rtbishop.lookingsat.Injector import com.rtbishop.lookingsat.Injector
import com.rtbishop.lookingsat.repo.Repository import com.rtbishop.lookingsat.repo.Repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.IOException
class MainViewModel(application: Application) : AndroidViewModel(application) { class MainViewModel(application: Application) : AndroidViewModel(application) {
private var repository: Repository = Injector.provideRepository(application) private val repository: Repository = Injector.provideRepository(application)
} private val preferences = PreferenceManager.getDefaultSharedPreferences(application)
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(application)
private val _gsp = MutableLiveData<GroundStationPosition>()
val gsp: LiveData<GroundStationPosition> = _gsp
fun updateLocation() {
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
val lat = location?.latitude ?: 51.5074
val lon = location?.longitude ?: 0.1278
val height = location?.altitude ?: 48.0
preferences.edit {
putDouble("LATITUDE", lat)
putDouble("LONGITUDE", lon)
putDouble("HEIGHT", height)
apply()
}
_gsp.postValue(GroundStationPosition(lat, lon, height))
}
}
fun updateTwoLineElementFile() {
val fileName = "tles.txt"
viewModelScope.launch(Dispatchers.IO) {
try {
getApplication<Application>().openFileOutput(fileName, Context.MODE_PRIVATE).use {
it.write(repository.fetchTleStream().readBytes())
}
Toast.makeText(getApplication(), "TLE file was updated", Toast.LENGTH_SHORT).show()
} catch (exception: IOException) {
Toast.makeText(getApplication(), "Could not update TLE", Toast.LENGTH_SHORT).show()
}
}
}
fun updateTransmittersDatabase() {
viewModelScope.launch(Dispatchers.IO) {
try {
repository.updateTransmittersDatabase()
Toast.makeText(getApplication(), "", Toast.LENGTH_SHORT).show()
} catch (exception: IOException) {
Toast.makeText(getApplication(), "", Toast.LENGTH_SHORT).show()
}
}
}
}
fun SharedPreferences.Editor.putDouble(key: String, double: Double): SharedPreferences.Editor =
putLong(key, java.lang.Double.doubleToRawLongBits(double))
fun SharedPreferences.getDouble(key: String, default: Double) =
java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))
+9
View File
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z" />
</vector>
+3 -3
View File
@@ -18,16 +18,16 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/timer_layout" android:id="@+id/timer_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_marginEnd="16dp">
<TextView <TextView
android:id="@+id/time_to_aos" android:id="@+id/time_to_aos"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:gravity="center" android:gravity="center"
android:text="@string/next_aos_pattern" android:text="@string/next_aos_pattern"
android:textSize="32sp" android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
+6 -18
View File
@@ -1,21 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/fetch_trans" android:id="@+id/menu_refresh"
android:title="@string/menu_fetch_transmitters" /> android:icon="@drawable/ic_refresh"
<item android:title="@string/menu_refresh"
android:id="@+id/save_to_db" app:showAsAction="always" />
android:title="@string/menu_save_to_db" />
<item
android:id="@+id/load_from_db"
android:title="@string/menu_load_from_db" />
<item
android:id="@+id/fetch_tle"
android:title="@string/menu_fetch_tle" />
<item
android:id="@+id/load_tle"
android:title="@string/menu_load_tle" />
<item
android:id="@+id/action_exit"
android:title="@string/menu_exit" />
</menu> </menu>
+1 -6
View File
@@ -19,12 +19,7 @@
<string name="height">Height AMSL: </string> <string name="height">Height AMSL: </string>
<string name="height_def">48.0m</string> <string name="height_def">48.0m</string>
<string name="menu_fetch_transmitters">Fetch Transmitters</string> <string name="menu_refresh">Refresh</string>
<string name="menu_save_to_db">Save to DB</string>
<string name="menu_load_from_db">Load from DB</string>
<string name="menu_fetch_tle">Fetch TLE</string>
<string name="menu_load_tle">Load TLE</string>
<string name="menu_exit">Exit</string>
<string name="next_aos_pattern">AOS in %02d:%02d:%02d</string> <string name="next_aos_pattern">AOS in %02d:%02d:%02d</string>
<string name="drawer_locator">Drawer Locator</string> <string name="drawer_locator">Drawer Locator</string>