web-dev-qa-db-ja.com

Android Q、プログラムでインターネット用の別のWiFi APに接続します

Android Qのように、いくつかのWiFi APIが制限されています。別のAPIを使用してインターネット用の別のWifi APに接続しようとしています。

以下は私のコードです:

    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);

これで接続できますが、インターネットは無効になっています。これは、Android docs。

私が試した別の方法は以下の通りです:

    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);

マニフェストで宣言された許可:

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

これを使用しても、動作に変化はありませんでした。

インターネット機能を備えた別のWifi APに正常に接続するためのAPIのシーケンスを教えてください。

10
Vinodh

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);

GoogleのエンジニアによるGoogleの Issue トラッカーから:

ネットワーク提案APIフローでは、ユーザーがアプリを承認する必要があります(プラットフォームはユーザーに承認を求める通知を投稿します)。アプリが承認されると、プラットフォームは今後の自動接続試行でアプリからのすべてのネットワークを考慮します。ただし、このAPIは、デバイスがプロビジョニングのためにAPに接続するタイミングを保証しません。したがって、WifiNetworkSuggestionは、提供されているユースケース(ピアツーピアのインスタント接続)に適したAPIサーフェスではありません。

WifiNetworkSpecifierを使用すると、上記のようにWifiアクセスポイントへのローカル接続が確立されます。この場合、デフォルトのネットワークは引き続き携帯電話です(他のアプリのインターネット接続を中断することはありません)。リクエストを行うアプリは、マルチネットワークAPIを使用して、確立された接続を介してトラフィックをルーティングする必要があります。 |ネットワーク|リクエストのonAvailable()コールバックで提供されるオブジェクトは、ローカルネットワーク経由でソケットを開くためにアプリが使用する必要があるハンドルです(- https://developer.Android.com/reference/Android/net/Networkを参照)。 .html#bindSocket(Java.net.DatagramSocket) と| Network |オブジェクトサーフェイスで利用できるその他のAPI。

お役に立てれば。

3

OnAvailable()コールバックでbindProcessToNetwork()を呼び出して、ネットワーク接続を回復してみてください。

ネットワークに接続:

    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);

バインドされたネットワークから切断します。

cm.unregisterNetworkCallback(networkCallback);
2
Neil.Ling

前述のように、 ここ 、Android 10は意図的にそれを作成したため、WifiNetworkSpecifierは実際のインターネット接続を防止します。ピアツーピア接続用です。

ただし、WifiNetworkSuggestion APIはインターネット接続を提供し、WifiNetworkSpecifier APIと同様に動作します。デバイスが現在どのWifiネットワークにも接続されていない限り、WifiNetworkSuggestion APIは指定されたネットワークに自動的に接続します。デバイスが初めて使用するときに、アプリがネットワークを提案できるかどうかを尋ねる通知が表示されます。 WifiNetworkSuggestion APIが機能するには、ユーザーがこの通知を受け入れる必要があります。

WifiNetworkSuggestionのドキュメントでAndroidが提供するコードにいくつかのコンパイルエラーがあることがわかりました。これが私が機能することがわかったコードです:

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);
0
Russell C.