mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Added initial code for the custom tle import from file
This commit is contained in:
1 parent
7c60fa9b2b
commit
3b5c3a8bb3
11 files changed
+118
-24
No files matched your search
@@ -1,5 +1,7 @@
|
||||
package com.rtbishop.look4sat.dagger.modules
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import com.rtbishop.look4sat.network.RemoteSource
|
||||
import com.rtbishop.look4sat.persistence.LocalSource
|
||||
import com.rtbishop.look4sat.repo.DefaultRepository
|
||||
@@ -13,7 +15,17 @@ class RepoModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideDefaultRepository(localSource: LocalSource, remoteSource: RemoteSource): Repository {
|
||||
return DefaultRepository(localSource, remoteSource)
|
||||
fun provideContentResolver(context: Context): ContentResolver {
|
||||
return context.applicationContext.contentResolver
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideDefaultRepository(
|
||||
resolver: ContentResolver,
|
||||
localSource: LocalSource,
|
||||
remoteSource: RemoteSource
|
||||
): Repository {
|
||||
return DefaultRepository(resolver, localSource, remoteSource)
|
||||
}
|
||||
}
|
||||
@@ -34,14 +34,12 @@ class RemoteDataSource @Inject constructor(
|
||||
private val client: OkHttpClient
|
||||
) : RemoteSource {
|
||||
|
||||
override suspend fun fetchTleStream(urlList: List<String>): InputStream {
|
||||
override suspend fun fetchTleStream(tleUrl: String): InputStream {
|
||||
val streamTable = Hashtable<String, InputStream>()
|
||||
withContext(Dispatchers.IO) {
|
||||
urlList.forEach {
|
||||
val request = Request.Builder().url(it).build()
|
||||
val stream = client.newCall(request).execute().body()?.byteStream()
|
||||
streamTable[it] = stream
|
||||
}
|
||||
val request = Request.Builder().url(tleUrl).build()
|
||||
val stream = client.newCall(request).execute().body()?.byteStream()
|
||||
streamTable[tleUrl] = stream
|
||||
}
|
||||
return SequenceInputStream(streamTable.elements())
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.io.InputStream
|
||||
|
||||
interface RemoteSource {
|
||||
|
||||
suspend fun fetchTleStream(urlList: List<String>): InputStream
|
||||
suspend fun fetchTleStream(tleUrl: String): InputStream
|
||||
|
||||
suspend fun fetchTransmitters(): List<Transmitter>
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package com.rtbishop.look4sat.repo
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import com.github.amsacode.predict4java.TLE
|
||||
import com.rtbishop.look4sat.data.SatEntry
|
||||
import com.rtbishop.look4sat.data.Transmitter
|
||||
@@ -29,12 +31,23 @@ import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultRepository @Inject constructor(
|
||||
private val resolver: ContentResolver,
|
||||
private val localSource: LocalSource,
|
||||
private val remoteSource: RemoteSource
|
||||
) : Repository {
|
||||
|
||||
override suspend fun updateEntriesFrom(urlList: List<String>) {
|
||||
val stream = remoteSource.fetchTleStream(urlList)
|
||||
override suspend fun updateEntriesFromFile(uri: Uri) {
|
||||
resolver.openInputStream(uri)?.use {
|
||||
withContext(Dispatchers.IO) {
|
||||
val tleList = TLE.importSat(it)
|
||||
val entries = tleList.map { SatEntry(it) }
|
||||
localSource.insertEntries(entries)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateEntriesFromUrl(tleUrl: String) {
|
||||
val stream = remoteSource.fetchTleStream(tleUrl)
|
||||
withContext(Dispatchers.IO) {
|
||||
val tleList = TLE.importSat(stream)
|
||||
val entries = tleList.map { SatEntry(it) }
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.rtbishop.look4sat.repo
|
||||
|
||||
import android.net.Uri
|
||||
import com.rtbishop.look4sat.data.SatEntry
|
||||
import com.rtbishop.look4sat.data.Transmitter
|
||||
|
||||
interface Repository {
|
||||
|
||||
suspend fun updateEntriesFrom(urlList: List<String>)
|
||||
suspend fun updateEntriesFromFile(uri: Uri)
|
||||
|
||||
suspend fun updateEntriesFromUrl(tleUrl: String)
|
||||
|
||||
suspend fun getAllEntries(): List<SatEntry>
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.rtbishop.look4sat.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.PackageManager
|
||||
@@ -52,6 +53,7 @@ import javax.inject.Inject
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private val pickFileReqCode = 111
|
||||
private val permLocationCode = 101
|
||||
private val permLocation = Manifest.permission.ACCESS_FINE_LOCATION
|
||||
private val permGranted = PackageManager.PERMISSION_GRANTED
|
||||
@@ -150,8 +152,17 @@ class MainActivity : AppCompatActivity() {
|
||||
requestLocationUpdate()
|
||||
it.lockButton()
|
||||
}
|
||||
drawerBinding.drawerBtnTle.setOnClickListener {
|
||||
viewModel.updateEntries()
|
||||
drawerBinding.drawerBtnTleFile.setOnClickListener {
|
||||
val openFileIntent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "text/*"
|
||||
}
|
||||
startActivityForResult(openFileIntent, pickFileReqCode)
|
||||
mainBinding.drawerLayout.closeDrawers()
|
||||
it.lockButton()
|
||||
}
|
||||
drawerBinding.drawerBtnTleUrl.setOnClickListener {
|
||||
viewModel.updateEntriesFromWeb()
|
||||
it.lockButton()
|
||||
}
|
||||
drawerBinding.drawerBtnTrans.setOnClickListener {
|
||||
@@ -204,4 +215,14 @@ class MainActivity : AppCompatActivity() {
|
||||
val navController = findNavController(R.id.nav_host)
|
||||
return navController.navigateUp(appBarConfig) || super.onSupportNavigateUp()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == pickFileReqCode && resultCode == Activity.RESULT_OK) {
|
||||
data?.data?.also { uri ->
|
||||
viewModel.updateEntriesFromFile(uri)
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.rtbishop.look4sat.ui
|
||||
|
||||
import android.location.LocationManager
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.*
|
||||
import com.github.amsacode.predict4java.GroundStationPosition
|
||||
import com.rtbishop.look4sat.data.Result
|
||||
@@ -46,7 +47,6 @@ class SharedViewModel @Inject constructor(
|
||||
private val _gsp = MutableLiveData<Result<GroundStationPosition>>().apply {
|
||||
value = Result.Success(prefsManager.getPosition())
|
||||
}
|
||||
private val urlList = listOf("https://celestrak.com/NORAD/elements/active.txt")
|
||||
private var calculationJob: Job? = null
|
||||
var isFirstLaunch = true
|
||||
|
||||
@@ -85,11 +85,25 @@ class SharedViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateEntries() {
|
||||
fun updateEntriesFromFile(uri: Uri) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val selected = repository.getSelectedEntries().map { it.catNum }
|
||||
repository.updateEntriesFrom(urlList)
|
||||
repository.updateEntriesFromFile(uri)
|
||||
repository.updateEntriesSelection(selected)
|
||||
_updateStatus.postValue(Result.Success(0))
|
||||
} catch (e: Exception) {
|
||||
_updateStatus.postValue(Result.Error(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateEntriesFromWeb() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val url = prefsManager.getTleUrl()
|
||||
val selected = repository.getSelectedEntries().map { it.catNum }
|
||||
repository.updateEntriesFromUrl(url)
|
||||
repository.updateEntriesSelection(selected)
|
||||
_updateStatus.postValue(Result.Success(0))
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -36,10 +36,12 @@ class PrefsManager @Inject constructor(
|
||||
private val keyAltitude = "altitude"
|
||||
private val keyRefreshRate = "rate"
|
||||
private val keyCompass = "compass"
|
||||
private val keyTleUrl = "tleUrl"
|
||||
private val defaultHoursAhead = 8
|
||||
private val defaultMinEl = 16.0
|
||||
private val defaultRefreshRate = "3000"
|
||||
private val defaultGSP = "0.0"
|
||||
private val defaultTleUrl = "https://celestrak.com/NORAD/elements/active.txt"
|
||||
|
||||
fun getHoursAhead(): Int {
|
||||
return preferences.getInt(keyHoursAhead, defaultHoursAhead)
|
||||
@@ -64,6 +66,10 @@ class PrefsManager @Inject constructor(
|
||||
return GroundStationPosition(lat, lon, alt)
|
||||
}
|
||||
|
||||
fun getTleUrl(): String {
|
||||
return preferences.getString(keyTleUrl, defaultTleUrl)!!
|
||||
}
|
||||
|
||||
fun setHoursAhead(hours: Int) {
|
||||
preferences.edit {
|
||||
putInt(keyHoursAhead, hours)
|
||||
@@ -94,6 +100,12 @@ class PrefsManager @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun setTleUrl(tleUrl: String) {
|
||||
preferences.edit {
|
||||
putString(keyTleUrl, tleUrl)
|
||||
}
|
||||
}
|
||||
|
||||
private fun SharedPreferences.Editor.putDouble(key: String, double: Double) {
|
||||
putLong(key, double.toRawBits())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="@color/themeIcon"
|
||||
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z" />
|
||||
</vector>
|
||||
@@ -94,16 +94,26 @@
|
||||
android:id="@+id/drawer_btn_loc"
|
||||
style="@style/DrawerHeader.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:drawableEnd="@drawable/ic_update_loc"
|
||||
android:text="@string/update_loc"
|
||||
app:layout_constraintBottom_toTopOf="@+id/drawer_btn_tle"
|
||||
app:layout_constraintBottom_toTopOf="@+id/drawer_btn_tle_file"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guidelineRight"
|
||||
app:layout_constraintStart_toStartOf="@+id/guidelineLeft"
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_lon_value" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/drawer_btn_tle"
|
||||
android:id="@+id/drawer_btn_tle_file"
|
||||
style="@style/DrawerHeader.Button"
|
||||
android:layout_width="0dp"
|
||||
android:drawableEnd="@drawable/ic_file_open"
|
||||
android:text="@string/update_tle_file"
|
||||
app:layout_constraintBottom_toTopOf="@+id/drawer_btn_tle_url"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guidelineRight"
|
||||
app:layout_constraintStart_toStartOf="@+id/guidelineLeft"
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_btn_loc" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/drawer_btn_tle_url"
|
||||
style="@style/DrawerHeader.Button"
|
||||
android:layout_width="0dp"
|
||||
android:drawableEnd="@drawable/ic_update_tle"
|
||||
@@ -111,7 +121,7 @@
|
||||
app:layout_constraintBottom_toTopOf="@+id/drawer_btn_trans"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guidelineRight"
|
||||
app:layout_constraintStart_toStartOf="@+id/guidelineLeft"
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_btn_loc" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_btn_tle_file" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/drawer_btn_trans"
|
||||
@@ -122,7 +132,7 @@
|
||||
app:layout_constraintBottom_toTopOf="@+id/drawer_btn_github"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guidelineRight"
|
||||
app:layout_constraintStart_toStartOf="@+id/guidelineLeft"
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_btn_tle" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/drawer_btn_tle_url" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/drawer_btn_github"
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
<string name="update_loc">Update location</string>
|
||||
<string name="update_loc_success">Location was updated</string>
|
||||
<string name="update_loc_failure">Check your Location settings</string>
|
||||
<string name="update_tle">Update TLE file</string>
|
||||
<string name="update_tle_success">TLE file was updated</string>
|
||||
<string name="update_tle_file" translatable="false">Update TLE from file</string>
|
||||
<string name="update_tle_file_success" translatable="false">TLE was updated</string>
|
||||
<string name="update_tle">Update TLE from URL</string>
|
||||
<string name="update_tle_success">TLE was updated</string>
|
||||
<string name="update_trans">Update transceivers</string>
|
||||
<string name="update_trans_success">Transceivers database was updated</string>
|
||||
<string name="update_failure">Check your internet connection</string>
|
||||
|
||||
Reference in new issue
Block a user