gpt4 book ai didi

android - 模拟位置不适用于 Android Pie 及更高版本

转载 作者:行者123 更新时间:2023-11-28 21:36:31 25 4
gpt4 key购买 nike

我编写了一个使用模拟位置提供程序的单元测试。接收到位置更新时测试通过,超时时失败。

测试在模拟的 Pixel 3、Android M 到 Android O 上运行良好。它在 Android P 和 Q 上超时。我还在带有 Q 的物理 Pixel 3 上测试,仍然失败。

一段时间以来,我一直在为这个问题苦苦思索,无法弄清楚发生了什么。

测试:

import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.location.Location
import android.location.LocationManager
import androidx.test.rule.GrantPermissionRule
import design.inhale.androidtestutils.InstrumentedTest
import design.inhale.datasource.observer.NullDataSourceListener
import design.inhale.testutils.Latch
import design.inhale.utils.locationManager
import design.inhale.utils.mock
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.core.Is
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule
import org.junit.Test

class DeviceLocationSourceTest: InstrumentedTest() {
private val mockProviderName = "MockProvider"
private val locationManager: LocationManager
get() = appContext.locationManager

@get:Rule
val permissionRule: GrantPermissionRule = grant(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)

@Before
fun init() {
addMockLocationProvider()
}

@After
fun deinit() {
instrumentation.waitForIdleSync()
removeMockLocationProvider()
}

@Test(timeout = 10_000)
fun receiveLocationUpdate() {
val latch = Latch()

val listener = object: LocationSourceListener {

override fun onDataUpdated(data: Location) {
with(data) {
assertThat(latitude, Is(equalTo(0.0)))
assertThat(longitude, Is(equalTo(0.0)))
}

latch.release()
}
}

mockLocationSource(listener).start()
instrumentation.waitForIdleSync() // in case we're hitting race conditions?

updateMockLocation(0.0, 0.0)

latch.await()
}

@Suppress("SameParameterValue")
private fun updateMockLocation(latitude: Double, longitude: Double) {
val location = Location(mockProviderName).mock(latitude, longitude)
locationManager.setTestProviderLocation(mockProviderName, location)
}

private fun mockLocationSource(listener: LocationSourceListener = NullDataSourceListener()) =
DeviceLocationSource(appContext, mockProviderName, listener)

private fun addMockLocationProvider() {
with(locationManager) {
try {
addTestProvider(
mockProviderName,
false,
false,
false,
false,
true,
true,
true,
0,
5)
} catch (e: IllegalArgumentException) {
// If this is caught, the mock provider already exists
}

setTestProviderEnabled(mockProviderName, true)
}
}

private fun removeMockLocationProvider() = locationManager.removeTestProvider(mockProviderName)
}

list :

<manifest package="design.inhale.locationapi"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

android测试/ list :

<?xml version="1.0" encoding="utf-8"?>
<manifest
package="design.inhale.locationapi"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

</manifest>

Location.mock():

@SuppressLint("ObsoleteSdkInt")
fun Location.mock(latitude: Double = 0.0, longitude: Double = 0.0, accuracy: Float = 0f): Location {

this.latitude = latitude
this.longitude = longitude
this.accuracy = accuracy
this.time = currentTimeMillis()

if (SDK_INT > JELLY_BEAN) this.elapsedRealtimeNanos = elapsedRealtimeNanos()

return this
}

最佳答案

原来我需要添加后台位置访问权限(我猜测试算作在后台运行?)。

添加了对测试 list 的权限。

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>`

并更改测试以授予它:

val permissionRule: GrantPermissionRule = grant(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION)

请注意,您需要确保没有将 ACCESS_BACKGROUND_LOCATION 添加到生产 list 中。如果 Google 发现您在没有充分理由的情况下使用此权限,他们将撤下您的应用。

关于android - 模拟位置不适用于 Android Pie 及更高版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58253545/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com