From 3b5c3a8bb3504b5a7ab8ac40caee9f5c540a159c Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sun, 10 May 2020 19:07:07 +0100 Subject: [PATCH] Added initial code for the custom tle import from file --- .../look4sat/dagger/modules/RepoModule.kt | 16 ++++++++++-- .../look4sat/network/RemoteDataSource.kt | 10 +++----- .../rtbishop/look4sat/network/RemoteSource.kt | 2 +- .../look4sat/repo/DefaultRepository.kt | 17 +++++++++++-- .../com/rtbishop/look4sat/repo/Repository.kt | 5 +++- .../com/rtbishop/look4sat/ui/MainActivity.kt | 25 +++++++++++++++++-- .../rtbishop/look4sat/ui/SharedViewModel.kt | 20 ++++++++++++--- .../rtbishop/look4sat/utility/PrefsManager.kt | 12 +++++++++ app/src/main/res/drawable/ic_file_open.xml | 9 +++++++ app/src/main/res/layout/drawer_header.xml | 20 +++++++++++---- app/src/main/res/values/strings.xml | 6 +++-- 11 files changed, 118 insertions(+), 24 deletions(-) create mode 100644 app/src/main/res/drawable/ic_file_open.xml diff --git a/app/src/main/java/com/rtbishop/look4sat/dagger/modules/RepoModule.kt b/app/src/main/java/com/rtbishop/look4sat/dagger/modules/RepoModule.kt index efffb9aa..8cbe6b73 100644 --- a/app/src/main/java/com/rtbishop/look4sat/dagger/modules/RepoModule.kt +++ b/app/src/main/java/com/rtbishop/look4sat/dagger/modules/RepoModule.kt @@ -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) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/network/RemoteDataSource.kt b/app/src/main/java/com/rtbishop/look4sat/network/RemoteDataSource.kt index 1c949d8f..8819529a 100644 --- a/app/src/main/java/com/rtbishop/look4sat/network/RemoteDataSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/network/RemoteDataSource.kt @@ -34,14 +34,12 @@ class RemoteDataSource @Inject constructor( private val client: OkHttpClient ) : RemoteSource { - override suspend fun fetchTleStream(urlList: List): InputStream { + override suspend fun fetchTleStream(tleUrl: String): InputStream { val streamTable = Hashtable() 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()) } diff --git a/app/src/main/java/com/rtbishop/look4sat/network/RemoteSource.kt b/app/src/main/java/com/rtbishop/look4sat/network/RemoteSource.kt index 8936b193..65e7654f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/network/RemoteSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/network/RemoteSource.kt @@ -5,7 +5,7 @@ import java.io.InputStream interface RemoteSource { - suspend fun fetchTleStream(urlList: List): InputStream + suspend fun fetchTleStream(tleUrl: String): InputStream suspend fun fetchTransmitters(): List } diff --git a/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt b/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt index fd9ce80a..26fbf113 100644 --- a/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt +++ b/app/src/main/java/com/rtbishop/look4sat/repo/DefaultRepository.kt @@ -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) { - 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) } diff --git a/app/src/main/java/com/rtbishop/look4sat/repo/Repository.kt b/app/src/main/java/com/rtbishop/look4sat/repo/Repository.kt index bc08bb37..58a431eb 100644 --- a/app/src/main/java/com/rtbishop/look4sat/repo/Repository.kt +++ b/app/src/main/java/com/rtbishop/look4sat/repo/Repository.kt @@ -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) + suspend fun updateEntriesFromFile(uri: Uri) + + suspend fun updateEntriesFromUrl(tleUrl: String) suspend fun getAllEntries(): List diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt index fde42c16..c6bc2781 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt @@ -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) + } + } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt index 89a4dfa6..2c02d9af 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt @@ -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>().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) { diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt index 7a967f23..5cd802a2 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt @@ -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()) } diff --git a/app/src/main/res/drawable/ic_file_open.xml b/app/src/main/res/drawable/ic_file_open.xml new file mode 100644 index 00000000..fa95c65b --- /dev/null +++ b/app/src/main/res/drawable/ic_file_open.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml index 6fcefad9..d8fdf3fe 100644 --- a/app/src/main/res/layout/drawer_header.xml +++ b/app/src/main/res/layout/drawer_header.xml @@ -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" /> + + + app:layout_constraintTop_toBottomOf="@+id/drawer_btn_tle_file" /> + app:layout_constraintTop_toBottomOf="@+id/drawer_btn_tle_url" /> Update location Location was updated Check your Location settings - Update TLE file - TLE file was updated + Update TLE from file + TLE was updated + Update TLE from URL + TLE was updated Update transceivers Transceivers database was updated Check your internet connection