这里有一个解决方案,它使用UiAutomator来从下拉状态栏启用或禁用“飞行模式”,如果启用,则关闭所有网络连接。它适用于大多数Android操作系统版本,并使用了用户Aorlinn(2019年10月12日)的答案的部分内容。
app/build.gradle
dependencies {
androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0"
}
AndroidManifest.xml
不需要额外的权限,甚至不需要 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
因为UiAutomator仅在状态栏UI上点击按钮。因此,应用程序不需要直接访问修改设备的Wifi或移动数据设置。
Kotlin
import android.os.Build
import android.provider.Settings
import androidx.test.espresso.matcher.ViewMatchers.assertThat
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObjectNotFoundException
import androidx.test.uiautomator.Until
import org.hamcrest.Matchers.`is`
import org.junit.Assert
import org.junit.Assume.assumeNoException
import org.junit.Assume.assumeThat
import java.io.IOException
private var airplaneModeOn = 0
private val OFF = 0
private val ON = 1
private var airplaneModeButtonPosition: Point? = null
@Test
fun checkAppWillWork_withNoInternetConnection() {
try {
airplaneModeOn = getCurrentAirplaneModeSetting()
} catch (e: Exception) {
e.printStackTrace()
assumeNoException("Cannot retrieve device setting of 'Airplane Mode'. Aborting the test.", e)
}
assertThat(airplaneModeOn, `is`(OFF))
toggleAeroplaneModeButton()
assumeThat("Cannot change the 'Aeroplane Mode' setting. Test aborted.", airplaneModeOn, `is`(ON))
assertThat(airplaneModeOn, `is`(ON))
}
@Throws(UiObjectNotFoundException::class)
private fun toggleAeroplaneModeButton() {
try {
airplaneModeOn = getCurrentAirplaneModeSetting()
} catch (e: SecurityException) {
e.printStackTrace()
Assert.fail()
} catch (e: IOException) {
e.printStackTrace()
Assert.fail()
}
val device = UiDevice.getInstance(getInstrumentation())
device.openQuickSettings()
val description = By.desc("AeroplaneMode")
device.wait(Until.hasObject(description), 2000)
var buttonClicked = clickObjectIfFound(device,
"Aeroplane mode", "Airplane mode", "機内モード", "Modo avión")
if (!buttonClicked) {
val screenWidth = device.displayWidth
val screenHeight = device.displayHeight
device.swipe((screenWidth * 0.80).toInt(), (screenHeight * 0.30).toInt(),
(screenWidth * 0.20).toInt(), (screenHeight * 0.30).toInt(), 50)
buttonClicked = clickObjectIfFound(device,
"Aeroplane mode", "Airplane mode", "機内モード", "Modo avión")
}
if (!buttonClicked) {
val screenWidth = device.displayWidth
val screenHeight = device.displayHeight
device.swipe((screenWidth * 0.20).toInt(), (screenHeight * 0.30).toInt(),
(screenWidth * 0.80).toInt(), (screenHeight * 0.30).toInt(), 50)
clickObjectIfFound(device,
"Aeroplane mode", "Airplane mode", "機内モード", "Modo avión")
}
device.wait(Until.hasObject(description), 6000)
getInstrumentation().context
.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
try {
airplaneModeOn = getCurrentAirplaneModeSetting()
} catch (e: SecurityException) {
e.printStackTrace()
Assert.fail()
} catch (e: IOException) {
e.printStackTrace()
Assert.fail()
}
}
@Throws(IOException::class, SecurityException::class)
private fun getCurrentAirplaneModeSetting(): Int {
if (Build.VERSION.SDK_INT in 26..28 ) {
val shellResponse = UiDevice
.getInstance(getInstrumentation())
.executeShellCommand("settings list global")
airplaneModeOn = when {
shellResponse.contains("airplane_mode_on=1") -> 1
shellResponse.contains("airplane_mode_on=0") -> 0
else -> throw IOException("Unsuitable response from adb shell command 'settings list global'")
}
} else {
airplaneModeOn = Settings.System.getInt(
getInstrumentation().context.contentResolver,
Settings.Global.AIRPLANE_MODE_ON,
0)
}
return airplaneModeOn
}
private fun clickObjectIfFound(device: UiDevice, vararg textLabels: String): Boolean {
for (languageVariant in textLabels) {
val availableButtons = device.findObjects(By.text(languageVariant))
if (availableButtons.size >= 1) {
if (airplaneModeButtonPosition == null) {
availableButtons[availableButtons.size - 1].click()
airplaneModeButtonPosition = availableButtons[availableButtons.size - 1].visibleCenter
return true
} else {
for (button in availableButtons) {
if (button.visibleCenter == airplaneModeButtonPosition) {
button.click()
airplaneModeButtonPosition = null
return true
}
}
}
}
}
return false
}
@After
fun cleanup() {
if (airplaneModeOn == ON) {
toggleAeroplaneModeButton()
assertThat(airplaneModeOn, `is`(OFF))
}
}
如果您的设备语言不是英语,您将需要调整字符串"Aeroplane mode"
。例如,您可以在此处检查大约70种语言的翻译:https://github.com/aosp-mirror/platform_frameworks_base/search?q=global_actions_toggle_airplane_mode