使用 WifiManager 打开 wifi 停止工作 Android 10

Turning on wifi using WifiManager stops to work on Android 10

我有以下代码,在 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(布尔值启用)

This method was deprecated in API level 29. Starting with Build.VERSION_CODES#Q, applications are not allowed to enable/disable Wi-Fi.

Compatibility Note: For applications targeting Build.VERSION_CODES.Q or above, this API will always return false and will have no effect.

If apps are targeting an older SDK ( Build.VERSION_CODES.P or below), they can continue to use this API.

根据文档,Apps 将无法再从 Android-10 API level 29[ 转向 Wi-Fi OFF/ON,直到 google 提供替代解决方案].

有关详细信息,请参阅 official documentation

issue 128554616 已在 google issuetracker 中创建了关于此的 issue 128554616

我们知道上面提到的 google 问题跟踪器提到我们没有替代 api 已弃用的 setWiFiEnabled,我想我们需要寻找替代品,所以我使用 InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("svc wifi enable"));InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand("svc wifi disable")); 而 运行 测试在 API 29 或更高版本的设备上切换 WiFi。

您仍然可以在旧设备上使用旧的 API(参见:official documentation),所以我是这样做的:

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”已标记为已弃用,但仍可在旧设备上使用。

我不知道问题出在哪里,因为Google已经回答了:

If apps are targeting an older SDK ( Build.VERSION_CODES.P or below), they can continue to use this API.

因此将您的 Target SDK 更改为 28,它在 Android Q 上运行良好。

或者如果您需要通过 Tasker 或 Automate 等第二个应用程序更改 WiFi 状态:

  1. 安装Android工作室
  2. 创建一个新的项目名称 WiFiOn with Empty Activity and SDK 28
  3. 添加注释行:
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();

    }
}
  1. minSdkVersiontargetSdkVersion改为28 build.grade(:app)
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.Whosebug.example"
        minSdkVersion 28
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
  1. 向AndroidMAnifest.xml添加权限
<?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"
...
  1. 使用 Android Studio 将其安装到您的 phone。

  2. 像 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
}