Skip to content

Commit

Permalink
CATROID-1605: Crash when using geolocation sensors (#4966)
Browse files Browse the repository at this point in the history
  • Loading branch information
JayTropper authored Nov 15, 2024
1 parent 48985da commit 43e8609
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@

package org.catrobat.catroid.uiespresso.formulaeditor

import android.Manifest
import android.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.rule.GrantPermissionRule
import org.catrobat.catroid.R
import org.catrobat.catroid.content.bricks.ChangeSizeByNBrick
import org.catrobat.catroid.testsuites.annotations.Cat
Expand Down Expand Up @@ -74,6 +77,7 @@ class FormulaEditorSensorListTest(
private val itemIndex: Int = index.toInt()
private var sensorName: String = name + param
private var isHeader = sensorHeader.isNotBlank()
private var isGpsSensor = false

private var sensorNumber: String? = null

Expand All @@ -86,6 +90,12 @@ class FormulaEditorSensorListTest(
sensorName = name
sensorNumber = param
}
if (sensorName.contains(str(R.string.formula_editor_sensor_longitude)) ||
sensorName.contains(str(R.string.formula_editor_sensor_latitude)) ||
sensorName.contains(str(R.string.formula_editor_sensor_altitude)) ||
sensorName.contains(str(R.string.formula_editor_sensor_location_accuracy))) {
isGpsSensor = true
}
}

private fun saveInitialSettings() {
Expand Down Expand Up @@ -132,6 +142,11 @@ class FormulaEditorSensorListTest(
restoreInitialSettings()
}

@JvmField
@Rule
var permissionRule: GrantPermissionRule = GrantPermissionRule.grant(
Manifest.permission.ACCESS_FINE_LOCATION
)
@Test
fun testSensorListElements() {
onBrickAtPosition(1).onChildView(withId(R.id.brick_change_size_by_edit_text))
Expand Down Expand Up @@ -162,6 +177,13 @@ class FormulaEditorSensorListTest(
)

onCategoryList().performSelect(sensorName)

if (isGpsSensor) {
onView(withId(R.id.formula_editor_keyboard_compute))
.perform(click())
pressBack()
}

sensorNumber?.let { sensor ->
val portNumber = when (sensor.trim()[sensor.length - 1]) {
'1' -> str(R.string.lego_port_1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Catroid: An on-device visual programming system for Android devices
* Copyright (C) 2010-2024 The Catrobat Team
* (<http://developer.catrobat.org/credits>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* An additional term exception under section 7 of the GNU Affero
* General Public License, version 3, is available at
* http://developer.catrobat.org/license_additional_term
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.catrobat.catroid.formulaeditor

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.location.GnssStatus
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.os.SystemClock
import androidx.core.app.ActivityCompat

class GpsStatusHandler(private val sensorHandler: SensorHandler) {
private var gnssCallback: GNSSCallback? = null
private var lastLocationGpsMillis: Long = 0
private var lastLocationGps: Location? = null

fun registerGNSSCallback(locationManager: LocationManager, context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
gnssCallback = GNSSCallback()
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
locationManager.registerGnssStatusCallback(context.mainExecutor, gnssCallback!!)
} else
gnssCallback = GNSSCallback()
locationManager.registerGnssStatusCallback(gnssCallback!!)
}

fun deregisterGNSSCallback(locationManager: LocationManager) {
if (gnssCallback != null) {
locationManager.unregisterGnssStatusCallback(gnssCallback!!)
}
}

fun setLastLocationAndGpsMillis(lastLocationGps: Location?, lastLocationGpsMillis: Long) {
this.lastLocationGps = lastLocationGps
this.lastLocationGpsMillis = lastLocationGpsMillis
}

private inner class GNSSCallback : GnssStatus.Callback() {
override fun onStopped() {
sensorHandler.setIsGpsConnected(false)
}

override fun onFirstFix(ttffMillis: Int) {
sensorHandler.setIsGpsConnected(true)
}

override fun onSatelliteStatusChanged(status: GnssStatus) {
if (lastLocationGps != null) {
sensorHandler.setIsGpsConnected(
SystemClock.elapsedRealtime() - lastLocationGpsMillis < 3000
)
}
}
}
}
Loading

0 comments on commit 43e8609

Please sign in to comment.