mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-04 14:13:47 -04:00
Merge pull request #336 from meshtastic/provideLocation
add provideLocation service start/stop
This commit is contained in:
@@ -179,8 +179,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
)
|
||||
)
|
||||
|
||||
private
|
||||
val tabsAdapter = object : FragmentStateAdapter(this) {
|
||||
private val tabsAdapter = object : FragmentStateAdapter(this) {
|
||||
|
||||
override fun getItemCount(): Int = tabInfos.size
|
||||
|
||||
@@ -200,7 +199,6 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
updateBluetoothEnabled()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Don't tell our app we have bluetooth until we have bluetooth _and_ location access
|
||||
*/
|
||||
@@ -213,7 +211,6 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
Manifest.permission.BLUETOOTH_ADMIN
|
||||
)
|
||||
|
||||
|
||||
if (getMissingPermissions(requiredPerms).isEmpty()) {
|
||||
/// ask the adapter if we have access
|
||||
bluetoothAdapter?.apply {
|
||||
@@ -532,7 +529,6 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
handleIntent(intent)
|
||||
@@ -659,8 +655,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
} */
|
||||
}
|
||||
|
||||
private
|
||||
var receiverRegistered = false
|
||||
private var receiverRegistered = false
|
||||
|
||||
private fun registerMeshReceiver() {
|
||||
unregisterMeshReceiver()
|
||||
@@ -680,7 +675,6 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Pull our latest node db from the device
|
||||
private fun updateNodesFromDevice() {
|
||||
model.meshService?.let { service ->
|
||||
@@ -724,7 +718,6 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
showSettingsPage() // Default to the settings page in this case
|
||||
}
|
||||
|
||||
|
||||
/// Called when we gain/lose a connection to our mesh radio
|
||||
private fun onMeshConnectionChanged(connected: MeshService.ConnectionState) {
|
||||
debug("connchange ${model.isConnected.value} -> $connected")
|
||||
@@ -773,6 +766,9 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
warn("Abandoning connect $ex, because we probably just lost device connection")
|
||||
model.isConnected.value = oldConnection
|
||||
}
|
||||
// if provideLocation enabled: Start providing location (from phone GPS) to mesh
|
||||
if (model.provideLocation.value == true && (oldConnection != connected))
|
||||
service.setupProvideLocation()
|
||||
}
|
||||
} else {
|
||||
// For other connection states, just slam them in
|
||||
@@ -842,8 +838,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
val meshServiceReceiver = object : BroadcastReceiver() {
|
||||
private val meshServiceReceiver = object : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) =
|
||||
exceptionReporter {
|
||||
@@ -891,8 +886,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
|
||||
private var connectionJob: Job? = null
|
||||
|
||||
private
|
||||
val mesh = object :
|
||||
private val mesh = object :
|
||||
ServiceClient<com.geeksville.mesh.IMeshService>({
|
||||
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
|
||||
}) {
|
||||
@@ -1269,4 +1263,3 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1015,12 +1015,12 @@ class MeshService : Service(), Logging {
|
||||
maybeUpdateServiceStatusNotification()
|
||||
}
|
||||
|
||||
private fun setupLocationRequest() {
|
||||
private fun setupLocationRequests() {
|
||||
stopLocationRequests()
|
||||
val mi = myNodeInfo
|
||||
val prefs = radioConfig?.preferences
|
||||
if (mi != null && prefs != null) {
|
||||
var broadcastSecs = prefs.positionBroadcastSecs
|
||||
val broadcastSecs = prefs.positionBroadcastSecs
|
||||
|
||||
var desiredInterval = if (broadcastSecs == 0) // unset by device, use default
|
||||
15 * 60 * 1000L
|
||||
@@ -1047,7 +1047,6 @@ class MeshService : Service(), Logging {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send in analytics about mesh connection
|
||||
*/
|
||||
@@ -1326,7 +1325,7 @@ class MeshService : Service(), Logging {
|
||||
hwModelStr,
|
||||
firmwareVersion,
|
||||
firmwareUpdateFilename != null,
|
||||
isBluetoothInterface && com.geeksville.mesh.service.SoftwareUpdateService.shouldUpdate(
|
||||
isBluetoothInterface && SoftwareUpdateService.shouldUpdate(
|
||||
this@MeshService,
|
||||
DeviceVersion(firmwareVersion)
|
||||
),
|
||||
@@ -1481,8 +1480,6 @@ class MeshService : Service(), Logging {
|
||||
reportConnection()
|
||||
|
||||
updateRegion()
|
||||
|
||||
setupLocationRequest() // start sending location packets if needed
|
||||
}
|
||||
|
||||
private fun handleConfigComplete(configCompleteId: Int) {
|
||||
@@ -1879,6 +1876,15 @@ class MeshService : Service(), Logging {
|
||||
info("in connectionState=$r")
|
||||
r.toString()
|
||||
}
|
||||
|
||||
override fun setupProvideLocation() = toRemoteExceptions {
|
||||
setupLocationRequests()
|
||||
}
|
||||
|
||||
override fun stopProvideLocation() = toRemoteExceptions {
|
||||
stopLocationRequests()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
object SLogging : Logging
|
||||
|
||||
/// Change to a new macaddr selection, updating GUI and radio
|
||||
@@ -326,7 +325,6 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
||||
|
||||
val devices = object : MutableLiveData<MutableMap<String, DeviceListEntry>>(mutableMapOf()) {
|
||||
|
||||
|
||||
/**
|
||||
* Called when the number of active observers change from 1 to 0.
|
||||
*
|
||||
@@ -439,7 +437,6 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
private var _binding: SettingsFragmentBinding? = null
|
||||
@@ -495,7 +492,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
|
||||
/// Set the correct update button configuration based on current progress
|
||||
private fun refreshUpdateButton(enable: Boolean) {
|
||||
debug("Reiniting the udpate button")
|
||||
debug("Reiniting the update button")
|
||||
val info = model.myNodeInfo.value
|
||||
val service = model.meshService
|
||||
if (model.isConnected.value == MeshService.ConnectionState.CONNECTED && info != null && info.shouldUpdate && info.couldUpdate && service != null) {
|
||||
@@ -629,7 +626,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
binding.usernameEditText.setText(name)
|
||||
})
|
||||
|
||||
|
||||
// Only let user edit their name or set software update while connected to a radio
|
||||
model.isConnected.observe(viewLifecycleOwner, Observer { _ ->
|
||||
updateNodeInfo()
|
||||
@@ -652,31 +648,39 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
requireActivity().hideKeyboard()
|
||||
}
|
||||
|
||||
binding.provideLocationCheckbox.isEnabled = isGooglePlayAvailable(requireContext())
|
||||
binding.provideLocationCheckbox.setOnCheckedChangeListener { view, isChecked ->
|
||||
// No matter what set our desired state in prefs
|
||||
model.provideLocation.value = isChecked
|
||||
|
||||
if (view.isPressed && isChecked) { // We want to ignore changes caused by code (as opposed to the user)
|
||||
if (view.isChecked) {
|
||||
debug("User changed location tracking to $isChecked")
|
||||
val hasLocationPermission = myActivity.hasLocationPermission()
|
||||
val hasBackgroundPermission = myActivity.hasBackgroundPermission()
|
||||
if (view.isPressed) { // We want to ignore changes caused by code (as opposed to the user)
|
||||
val hasLocationPermission = myActivity.hasLocationPermission()
|
||||
val hasBackgroundPermission = myActivity.hasBackgroundPermission()
|
||||
|
||||
// Don't check the box until the system setting changes
|
||||
view.isChecked = hasLocationPermission && hasBackgroundPermission
|
||||
// Don't check the box until the system setting changes
|
||||
view.isChecked = hasLocationPermission && hasBackgroundPermission
|
||||
|
||||
if (!hasLocationPermission) // Make sure we have location permission (prerequisite)
|
||||
myActivity.requestLocationPermission()
|
||||
if (hasLocationPermission && !hasBackgroundPermission)
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.background_required)
|
||||
.setMessage(R.string.why_background_required)
|
||||
.setNeutralButton(R.string.cancel) { _, _ ->
|
||||
debug("User denied background permission")
|
||||
}
|
||||
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
||||
myActivity.requestBackgroundPermission()
|
||||
}
|
||||
.show()
|
||||
if (!hasLocationPermission) // Make sure we have location permission (prerequisite)
|
||||
myActivity.requestLocationPermission()
|
||||
if (hasLocationPermission && !hasBackgroundPermission)
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.background_required)
|
||||
.setMessage(R.string.why_background_required)
|
||||
.setNeutralButton(R.string.cancel) { _, _ ->
|
||||
debug("User denied background permission")
|
||||
}
|
||||
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
||||
myActivity.requestBackgroundPermission()
|
||||
}
|
||||
.show()
|
||||
|
||||
if (view.isChecked)
|
||||
model.provideLocation.value = isChecked
|
||||
model.meshService?.setupProvideLocation()
|
||||
}
|
||||
}
|
||||
else {
|
||||
model.provideLocation.value = isChecked
|
||||
model.meshService?.stopProvideLocation()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,16 +909,14 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
initClassicScan()
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user has not turned on location access throw up a toast warning
|
||||
*/
|
||||
// If the user has not turned on location access throw up a toast warning
|
||||
private fun checkLocationEnabled() {
|
||||
|
||||
fun hasGpsSensor(): Boolean =
|
||||
fun hasGps(): Boolean =
|
||||
myActivity.packageManager.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS)
|
||||
|
||||
// If they don't have google play FIXME for now we don't check for location access
|
||||
if (hasGpsSensor() && isGooglePlayAvailable(requireContext())) {
|
||||
// FIXME If they don't have google play for now we don't check for location enabled
|
||||
if (hasGps() && isGooglePlayAvailable(requireContext())) {
|
||||
// We do this painful process because LocationManager.isEnabled is only SDK28 or latet
|
||||
val builder = LocationSettingsRequest.Builder()
|
||||
builder.setNeedBle(true)
|
||||
@@ -992,7 +994,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
scanModel.startScan()
|
||||
|
||||
// system permissions might have changed while we were away
|
||||
binding.provideLocationCheckbox.isChecked = myActivity.hasBackgroundPermission() && (model.provideLocation.value ?: false)
|
||||
binding.provideLocationCheckbox.isChecked = myActivity.hasLocationPermission() && myActivity.hasBackgroundPermission() && (model.provideLocation.value ?: false) && isGooglePlayAvailable(requireContext())
|
||||
|
||||
myActivity.registerReceiver(updateProgressReceiver, updateProgressFilter)
|
||||
|
||||
@@ -1015,4 +1017,3 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user