相关文章推荐

安卓Q,以编程方式连接到不同的WiFi接入点进行上网

22 人关注

在Android Q中,有几个WiFi API受到限制。我正试图使用其他的API来连接不同的Wifi AP上网。

Below is my code :

    WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
    builder.setSsid("wifi-ap-ssid");
    builder.setWpa2Passphrase("wifi-ap-password");
    WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
    NetworkRequest.Builder networkRequestBuilder1 = new NetworkRequest.Builder();
    networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
    networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);
    NetworkRequest nr = networkRequestBuilder1.build();
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    cm.requestNetwork(nr, callback);

这使我能够连接,但互联网被禁用。这是在安卓文档中定义的工作。

我尝试的其他方法如下。

    WifiNetworkSuggestion.Builder wifiNetworkSuggestionBuilder1 = new WifiNetworkSuggestion.Builder();
    wifiNetworkSuggestionBuilder1.setSsid("wifi-ap-ssid");
    wifiNetworkSuggestionBuilder1.setWpa2Passphrase("wifi-ap-password");
    WifiNetworkSuggestion wifiNetworkSuggestion = wifiNetworkSuggestionBuilder1.build();
    List<WifiNetworkSuggestion> list = new ArrayList<>();
    list.add(wifiNetworkSuggestion);
    wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    wifiManager.removeNetworkSuggestions(new ArrayList<WifiNetworkSuggestion>());
    wifiManager.addNetworkSuggestions(list);

宣布允许在Manifest :

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

使用这个并没有在行为上改变什么。

请告诉我们成功连接到不同的具有互联网功能的Wifi AP的API序列。

5 个评论
关于这个问题,谷歌有一个开放的票据。我建议你们对这个票据进行评论和发言,因为这将有助于引起谷歌的注意。 issuetracker.google.com/issues/138335744
@AnandKhinvasara : 因为,这些API没有提供互联网功能。我正在显示一个弹出窗口,让用户进入设置并手动连接到AP。希望这种替代方法能适用于你的情况。
我知道,但这不是一个好的解决方案。谷歌应该解决这个问题。
@AnandKhinvasara : 同意。
我得到了它的工作。请检查我的答案。
android
android-wifi
android-developer-api
android-connectivitymanager
android-10.0
Vinodh
Vinodh
发布于 2019-07-01
5 个回答
Neil.Ling
Neil.Ling
发布于 2020-08-10
已采纳
0 人赞同

试着在onAvailable()回调中调用bindProcessToNetwork()来重新获得网络连接,对我来说效果不错。

Connect to network:

    WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
    builder.setSsid("wifi-ap-ssid");
    builder.setWpa2Passphrase("wifi-ap-password");
    WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
    NetworkRequest.Builder networkRequestBuilder1 = new NetworkRequest.Builder();
    networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
    networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);
    NetworkRequest nr = networkRequestBuilder1.build();
    ConnectivityManager cm = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    ConnectivityManager.NetworkCallback networkCallback = new 
        ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            super.onAvailable(network);
            Log.d(TAG, "onAvailable:" + network);
            cm.bindProcessToNetwork(network);
    cm.requestNetwork(nr, networkCallback);

Disconnect from the bound network:

cm.unregisterNetworkCallback(networkCallback);
    
mono
此答案不能解决问题 此连接方式不能访问互联网
你救了我的命,非常感谢!尊敬的各位领导
Anand Khinvasara
Anand Khinvasara
发布于 2020-08-10
0 人赞同

WifiNetworkSuggestion API用于建议用户加入一个AP(系统将发布一个通知让用户加入)。

使用WifiNetworkSpecifier来发送你的请求。使用onAvailable()中提供的网络对象。

WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
builder.setSsid("wifi-ap-ssid");
builder.setWpa2Passphrase("wifi-ap-password");
WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);
NetworkRequest networkRequest = networkRequestBuilder.build();
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.requestNetwork(networkRequest, networkCallback);
networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                //Use this network object to Send request. 
                //eg - Using OkHttp library to create a service request
                 //Service is an OkHttp interface where we define docs. Please read OkHttp docs
                 Service service = null;
                 OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
                okHttpBuilder.socketFactory(network.getSocketFactory());
                service = new Retrofit.Builder()                                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create(gson))
                         .client(okHttpBuilder.build())
                         .build()
                         .create(Service.class);
               Observable<Object> observable = null;
               try {
                  if (service != null) {
                     observable = service.yourRestCall();
                  Subscriber<Object> sub = new Subscriber< Object >() {
                     @Override
                     public void onError(Throwable e) {
                        //Do on error
                     @Override
                     public void onNext(Object logs) {
                        //Do on next
                 if(observable != null) {
                     observable.subscribeOn(Schedulers.io())
                                          .observeOn(AndroidSchedulers.mainThread()).subscribe(sub);
                super.onAvailable(network);

在你完成了对Wifi接入点的使用后,应

connectivityManager.unregisterNetworkCallback(networkCallback);

From Google's Issue谷歌工程师的追踪器。

网络建议API流程要求用户批准该应用(平台发布通知要求用户批准)。一旦应用程序被批准,平台将在未来的自动连接尝试中考虑该应用程序的所有网络。但是,这个API并不能保证设备何时连接到你的AP进行配置。所以,WifiNetworkSuggestion不是所提供的用例(点对点即时连接)的正确API面。

使用WifiNetworkSpecifier可以建立一个与上面提到的wifi接入点的本地连接。在这种情况下,默认网络仍然是蜂窝网络(我们不会破坏其他应用程序的互联网连接)。提出请求的应用程序应该使用多网络API,在已建立的连接上路由其流量。在请求的onAvailable()回调中提供的|Network|对象是应用程序需要使用的句柄,用于在本地网络上打开套接字(查看https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.DatagramSocket)。和其他类似的API在|网络|对象表面可用。

Hope this helps.

用这段代码,我得到了正确的AP的授权窗口......但当我按下连接键时,它却不工作。获得IP地址,然后重新连接到正常网络。有什么想法吗?谢谢你。
你好,@Anand Khinvasara,你能不能把这个的完整代码贴出来?我在以编程方式连接时遇到了很多没有网络的问题。谢谢!
好吧,我已经尝试了WifiNetworkSpecifier ...我有这样一个问题,当一个网络被选中时,设备不会连接到网络上,我也试过文档代码,有什么办法可以解决没有互联网连接的本地网络的问题?
Russell C.
Russell C.
发布于 2020-08-10
0 人赞同

如上所述 here 安卓10系统有意让WifiNetworkSpecifier阻止实际的互联网连接。它是为了点对点的连接。

而WifiNetworkSuggestion API则提供互联网连接,其行为与WifiNetworkSpecifier API类似。只要设备是 目前没有连接到任何Wifi网络 ,WifiNetworkSuggestion API将自动连接到指定的网络。设备第一次使用时,会出现一个通知,询问该应用是否可以推荐网络。用户必须接受这个通知,WifiNetworkSuggestion API才能工作。

我发现Android提供的WifiNetworkSuggestion文档中的代码有一些编译错误。以下是我发现可以工作的代码。

final WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
.setSsid("SSID here")
.setWpa2Passphrase("password here")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
// Optional extra suggesstion, you can delete this or add more
final WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion.Builder()
.setSsid("SSID here 2")
.setWpa2Passphrase("password here 2")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();
final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion>();
suggestionsList.add(suggestion1);
suggestionsList.add(suggestion2); // Optional extra suggestion
final WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
     // Error handling
final IntentFilter intentFilter = new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override public void onReceive(Context context, Intent intent) {
        if (!intent.getAction().equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
              return;
        // Post connection
getApplicationContext().registerReceiver(broadcastReceiver, intentFilter);
    
这是否意味着我被迫使用WiFiNetworkSuggestion来连接到WiFi并实际使用互联网?我能够使用WiFiNetworkSpecifier连接到WiFi,但没有实际的互联网接入。
是的,你将需要使用WifiNetworkSuggestion。WifiNetworkSpecifier是指如果你想连接到一个网络,用于互联网访问以外的某些目的。
Fung
Fung
发布于 2020-08-10
0 人赞同

You should use Wi-Fi网络建议API in Q

final WifiNetworkSuggestion suggestion1 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test111111")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()
final WifiNetworkSuggestion suggestion2 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test222222")
  .setWpa2Passphrase("test123456")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()
final WifiNetworkSuggestion suggestion3 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test333333")
  .setWpa3Passphrase("test6789")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()
final List<WifiNetworkSuggestion> suggestionsList =
  new ArrayList<WifiNetworkSuggestion> {{
    add(suggestion1);
    add(suggestion2);
    add(suggestion3);
final WifiManager wifiManager =
  (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
  new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(
      WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
      return;
    // do post connect processing here..
context.registerReceiver(broadcastReceiver, intentFilter);
    
它对使用WifiNetworkSpecifier建立的连接有效吗?
谢谢你的答复。但是,我看到网络建议没有提供互联网能力。你有什么其他的解决方法吗?
对我来说,status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS始终是真的。因此,我不能使它工作
spring.ace
spring.ace
发布于 2020-08-10
0 人赞同

ConnectivityManager.NetworkCallback() onAvailable(Network) 回调中(在你设置了你的 WifiNetworkSpecifier.Builder() NetworkRequest.Builder() 之后),调用 ConnectivityManager.bindProcessNetwork 来引导你在连接网络上的流量,正如 Network 中所记录的那样API。 https://developer.android.com/reference/android/net/Network

识别一个网络。它通过 ConnectivityManager.NetworkCallback 提供给应用程序,以响应主动的 ConnectivityManager#requestNetwork 或被动的 ConnectivityManager#registerNetworkCallback 调用。它被用来引导流量到给定的网络,要么通过目标的SocketFactory在Socket基础上,要么通过ConnectivityManager#bindProcessToNetwork在整个进程中。

private inner class MyCallback : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { // Call this method once this callback is triggered after // your call to mConnectivityManager.requestNetwork() mConnectivityManager.bindProcessToNetwork(network)
 
推荐文章