我有以下代码,在 Android 10 之前运行良好。但它无法在 Android 10 设备中打开 wifi。
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
boolean res = wifiMgr.setWifiEnabled(true);
//res value is set to false above because setWifiEnabled returns false on Android 10
以下是我在
AndroidManifest.xml
的权限
<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>
<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>
<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>
<uses-permission android:name=\"android.permission.INTERNET\"/>
<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>
我什至动态地请求这些权限。但这似乎也没有帮助。
问题:
Android 10 有什么变化吗?我应该做更多的事情来从我的应用程序以编程方式打开 wifi 吗?
public boolean setWifiEnabled(布尔启用)
此方法在 API 级别 29 中已弃用。 从 Build.VERSION_CODES#Q 开始,不允许应用程序启用/禁用 Wi-Fi。
兼容性注意:对于面向 Build.VERSION_CODES.Q 或更高版本的应用程序,此 API 将始终返回 false 并且无效。
如果应用程序面向较旧的 SDK(Build.VERSION_CODES.P 或更低版本),则可以继续使用此 API。
根据文档,
Apps
将无法再从Wi-Fi OFF/ON
转向Android-10 API level 29
[直到google提供替代解决方案]。
更多信息请参阅官方文档。
并且在谷歌issuetracker
中已经创建了一个关于此问题的
问题128554616。
您仍然可以在旧设备上使用旧的 API(请参阅:官方文档),所以这就是我所做的:
val wifiMgr = this.applicationContext.getSystemService(WIFI_SERVICE) as WifiManager
val alertDial: AlertDialog.Builder = AlertDialog.Builder(this)
//
//=============== Start Wi-Fi if needed ====================
// Check Wi-Fi state: 1=disabled WIFI_STATE_DISABLED
if (wifiMgr.wifiState == 1) {
alertDial.setMessage(R.string.wifi)
.setCancelable(false)
.setPositiveButton(R.string.yes) { _, _ -> // Enable wifi
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 0)
} else {
wifiMgr.isWifiEnabled = true
}
}
.setNegativeButton(R.string.no) { _, _ -> // Disable wifi
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 0)
} else {
wifiMgr.isWifiEnabled = false
}
}
alertDial.show()
}
}
“wifiMgr.isWifiEnabled”被标记为已弃用,但仍适用于较旧的设备。
正如我们所知,上述谷歌问题跟踪器提到我们没有已弃用的 setWiFiEnabled 的替代 API,我想我们需要寻找替代方案,因此我在运行测试时使用
InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("svc wifi enable"));
或 InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("svc wifi disable"));
在 API 29 或更高版本的设备上切换 WiFi。
我不知道问题出在哪里,因为谷歌已经回答了:
如果应用程序面向较旧的 SDK(Build.VERSION_CODES.P 或更低版本),则可以继续使用此 API。
因此将您的 Target SDK 更改为 28,它在 Android Q 上运行良好。
或者如果您需要通过 Tasker 或 Automate 等第二个应用程序更改 WiFi 状态:
import androidx.appcompat.app.AppCompatActivity;
import android.net.wifi.WifiManager;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add WiFi On Part
WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true); // true or false to activate/deactivate wifi
// Add Toast if you want to
Toast toast = Toast.makeText(getApplicationContext(), "WiFi on", Toast.LENGTH_SHORT);
toast.show();
// Add Close Activity immediatelly
finish();
}
}
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.stackoverflow.example"
minSdkVersion 28
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.p1apps.wifion">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<application
android:allowBackup="true"
...
使用Android Studio将其安装到您的手机上。
像 3 中那样创建一个新项目,并将其命名为 WiFiOff 并在 MainActivity 中更改行后重复所有步骤:
...
wifi.setWifiEnabled(false); // true or false to activate/deactivate wifi
...
Toast toast = Toast.makeText(getApplicationContext(), "WiFi off",
...
我们可以在 Q 或以上版本中实用地启用禁用 wifi
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 0)
} else {
wifiMgr.isWifiEnabled = true
}
我发现 WiFiManager.disableNetwork() 可以完成这项工作:
LWifiConf := TJWifiConfiguration.Wrap( List.get(i) );
LSsid := JStringToString( LWifiConf.SSID );
LNetId := LWifiConf.networkId;
Resb:= WiFiManager.disableNetwork(LNetId);
Memo1.Lines.Add('disableNetwork action: ' + Resb.ToString);
它会断开连接并且不会重新连接,至少在 wifi 循环关闭之前是这样。 在 Android 版本 6.0 和 SDK_INT 25 上进行测试
要重新连接,我们可以通过编程再次执行。