以编程方式连接到Android Q中的Wifi

时间:2020-07-27 22:49:54

标签: android wifi android-wifi android-10.0

我有此功能可以在Wifi网络中进行连接,在Android 10以下可以正常工作,但是当我在Android 10上进行尝试时,我已经成功建立了连接,但是没有互联网,我知道它是{{3 }},但我发现这个a bug in Android 10可以毫无问题地从Android 10连接到wifi。 我被封锁了好几天。

我的功能:

private void connectToWifi(String ssid, String password)
    {
        WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            try {
                Log.e(TAG,"connection wifi pre Q");
                WifiConfiguration wifiConfig = new WifiConfiguration();
                wifiConfig.SSID = "\"" + ssid + "\"";
                wifiConfig.preSharedKey = "\"" + password + "\"";
                int netId = wifiManager.addNetwork(wifiConfig);
                wifiManager.disconnect();
                wifiManager.enableNetwork(netId, true);
                wifiManager.reconnect();

            } catch ( Exception e) {
                e.printStackTrace();
            }
        } else {
            Log.e(TAG,"connection wifi  Q");

            WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
                .setSsid( ssid )
                .setWpa2Passphrase(password)
                    .build();

            NetworkRequest networkRequest = new NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .setNetworkSpecifier(wifiNetworkSpecifier)
                    .build();

             connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);


                 networkCallback = new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    super.onAvailable(network);

                     connectivityManager.bindProcessToNetwork(network);
                    Log.e(TAG,"onAvailable");
                }

                  @Override
                  public void onLosing(@NonNull Network network, int maxMsToLive) {
                      super.onLosing(network, maxMsToLive);
                      Log.e(TAG,"onLosing");
                  }

                  @Override
                public void onLost(Network network) {
                    super.onLost(network);
                    Log.e(TAG, "losing active connection");
                }

                @Override
                public void onUnavailable() {
                    super.onUnavailable();
                    Log.e(TAG,"onUnavailable");
                }
            };
            connectivityManager.requestNetwork(networkRequest,networkCallback);


        }
    }

7 个答案:

答案 0 :(得分:2)

如果要使用INTERNET连接到WiFi,则应使用这种 NetworkRequest

NetworkRequest request = new NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
    .setNetworkSpecifier(wifiNetworkSpecifier)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
    .build();

此外,您需要为过程指定默认路由,以永久性地向连接的WiFi AP发送请求。只需在 onAvaliable 下的 NetworkCallback 中添加下一个方法的调用即可,如下所示:

networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        createNetworkRoute(network, connectivityManager);
        }
    };
    if (connectivityManager!= null) connectivityManager.requestNetwork(request, networkCallback);

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private static void createNetworkRoute(Network network, ConnectivityManager connectivityManager) {
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
          connectivityManager.bindProcessToNetwork(network);
     } else {
          ConnectivityManager.setProcessDefaultNetwork(network);
     }
 } 

不要忘记断开与绑定网络的连接:

connectivityManager.unregisterNetworkCallback(networkCallback);

最后,您可以在WifiUtils之类的不同库中找到最佳实践。

答案 1 :(得分:1)

我也面临同样的问题,即使在 3 个月后我也无法解决这个问题。但我找到了一个很棒很酷的解决方案。

startActivity(new Intent("android.settings.panel.action.INTERNET_CONNECTIVITY"))

只需添加这些线路,而不是从应用程序连接到 wifi,这将提示用户选择一个 wifi 并连接,一旦用户这样做,它就会连接到 wifi 并且它也会有互联网。< /p>

仅从应用程序连接到 wifi 将无法访问互联网。这样做,这是最好的解决方案。

答案 2 :(得分:0)

如果您具有root访问权限(adb root):

  1. 手动连接到您选择的Wifi网络。

  2. 拉出这些ADB文件:

adb pull /data/misc/wifi/WifiConfigStore.xml
adb pull /data/misc/wifi/WifiConfigStore.xml.encrypted-checksum
  1. 保存在指定Wifi网络的文件夹中:
Ex:  GarageWifi
Ex:  BusinessWifi

复制到您选择的位置。 请勿更改您提取的文件的名称。

  1. 只要您想连接到所需的wifi网络:
adb push <location>\WifiConfigStore.xml /data/misc/wifi/
adb push <location>\WifiConfigStore.xml.encrypted-checksum /data/misc/wifi/

adb reboot

答案 3 :(得分:0)

您可以尝试使用wifisuggestion api,我可以使用它们进行连接。

final WifiNetworkSuggestion suggestion1 =
            new WifiNetworkSuggestion.Builder()
                    .setSsid("YOUR_SSID")
                    .setWpa2Passphrase("YOUR_PRE_SHARED_KEY")
                    .build();
    final List<WifiNetworkSuggestion> suggestionsList =
            new ArrayList<WifiNetworkSuggestion>();
    suggestionsList.add(suggestion1);

    WifiManager wifiManager =
            (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    int status = wifiManager.addNetworkSuggestions(suggestionsList);
    if (status == 0 ){
        Toast.makeText(this,"PSK network added",Toast.LENGTH_LONG).show();
        Log.i(TAG, "PSK network added: "+status);
    }else {
        Toast.makeText(this,"PSK network not added",Toast.LENGTH_LONG).show();
        Log.i(TAG, "PSK network not added: "+status);
    }

答案 4 :(得分:0)

因此,对我来说,解决方案是使用 targetSdkVersion 28 编译您的应用。 要连接wifi,请使用此功能

connectToWifi(String ssid, String key)

这只是暂时的解决方法,正在等待Google发布此错误的修复程序,以了解向Google报告的问题的更多信息:issuetracker.google.com/issues/138335744

public void connectToWifi(String ssid, String key) {

Log.e(TAG, "connection wifi pre Q");
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "\"" + ssid + "\"";
wifiConfig.preSharedKey = "\"" + key + "\"";
int netId = wifiManager.addNetwork(wifiConfig);
if (netId == -1) netId = getExistingNetworkId(wifiConfig.SSID);

wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();

}

答案 5 :(得分:0)

到目前为止,在我测试过的大多数设备上,什么对我有用(例外是Im目前正在研究的OnePlus,一旦我了解更多,它将进行更新,请参阅底部列表)。

下面的代码是用Kotlin编写的,如果需要的话,请用谷歌搜索如何隐藏到Java。

创建一个API> = 29所需的NetworkCallback(之前不是必需的,但可以使用)

val networkCallback = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // To make sure that requests don't go over mobile data
            // This is preventing a OnePlus model from communicating correctly (still investigating)
            connectivityManager.bindProcessToNetwork(network)
        } else {
            connectivityManager.setProcessDefaultNetwork(network)
        }
    }
}

按如下所示连接到网络

val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
    .setSsid(ssid)
    .setWpa2Passphrase(pass)
    .build()

networkRequest = NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
// Add the below 2 lines if the network should have internet capabilities.
// Adding/removing other capabilities has made no known difference so far
//    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
//    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
    .setNetworkSpecifier(wifiNetworkSpecifier)
    .build()

connectivityManager.requestNetwork(networkRequest, networkCallback)

在这里需要注意的是'networkRequest'变量是全局变量。据我了解,here要求它是可用的并且不能在函数中调用,这样它就不会被GC收集,并且在不再需要网络时将其设置为null,如下所示

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    //This is required for Xiaomi models for disconnecting
    connectivityManager.bindProcessToNetwork(null)
} else {
    connectivityManager.setProcessDefaultNetwork(null)
}
connectivityManager.unregisterNetworkCallback(it)
networkRequest = null

一些小技巧:

  • 现在将打开一个系统对话框,该应用分别调用onPause和onResume。这影响了我关于自动连接到IoT设备的逻辑。

  • 关于测试,我还不能仅通过使用espresso来解决该对话框,它可能会阻止某些在API 29之前运行的测试。可以使用其他框架(例如uiautomator)来实现。就我而言,我将测试调整为可以工作,直到出现对话框,然后再运行进一步的测试。 使用Intents.init()不起作用。

  • 找到网络后,将调用
  • onUnavailable,但用户会取消。当找不到网络或用户在找到网络之前取消对话框时,不会调用该方法。这是我通过调试发现的结果

已测试的设备列表:

  • Google Pixel 2-没问题
  • 三星S10 SM-G970F-没问题
  • 三星S9 SM-G960F-没问题
  • One Plus 5(OxegenOS 10.0.1)-自动连接的主要问题
  • 小米米Note 10-断开连接的问题(已修复)
  • 三星A50-成功连接后(有时)重复出现该对话框
  • Huawei Mate Pro 20-成功连接后(有时)重复出现对话框

答案 6 :(得分:0)

从 Android 10 开始,我必须使用以下代码连接到特定的 wifi 网络。

private ConnectivityManager mConnectivityManager;

@Override
    public void onCreate(@Nullable Bundle savedInstanceState){
// instantiate the connectivity manager
        mConnectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);

}

public void connect(String ssid, String password) {
        NetworkSpecifier networkSpecifier  = new WifiNetworkSpecifier.Builder()
                  .setSsid(ssid)
                  .setWpa2Passphrase(password)
                  .setIsHiddenSsid(true) //specify if the network does not broadcast itself and OS must perform a forced scan in order to connect
                  .build();
        NetworkRequest networkRequest  = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .setNetworkSpecifier(networkSpecifier)
                .build();
        mConnectivityManager.requestNetwork(networkRequest, mNetworkCallback);
    }
    
    public void disconnectFromNetwork(){
        //Unregistering network callback instance supplied to requestNetwork call disconnects phone from the connected network
        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
    }
    
    private ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager.NetworkCallback(){
            @Override
            public void onAvailable(@NonNull Network network) {
                super.onAvailable(network);
                //phone is connected to wifi network
            }
    
            @Override
            public void onLosing(@NonNull Network network, int maxMsToLive) {
                super.onLosing(network, maxMsToLive);
                //phone is about to lose connection to network
            }
    
            @Override
            public void onLost(@NonNull Network network) {
                super.onLost(network);
                //phone lost connection to network
            }
    
            @Override
            public void onUnavailable() {
                super.onUnavailable();
                //user cancelled wifi connection
            }
        };

参考资料: https://anutoshdatta.medium.com/new-wifi-apis-on-android-10-481c525108b7 https://developer.android.com/guide/topics/connectivity/wifi-suggest

相关问题