0

私は特にWiFi上でのみHTTP接続を行う必要があるアンドロイドアプリを開発しています。 Android L以上の接続に関連した変更がたくさんあったようです。私はHttpURLConnectionのは、そのネットワークを拘束得るためにnetworkObject.openConnectionを行うことができるはずConnectivityManagerとネットワークAPIドキュメントを1として特定の接続経由でアンドロイドアプリでトラフィックを送信する

ConnectivityManager manager = (ConnectivityManager) 
ctx.getSystemService(Context.CONNECTIVITY_SERVICE); 
Network[] allNetworks = manager.getAllNetworks(); 

for(Network network : allNetworks) { 
    NetworkInfo info = manager.getNetworkInfo(network); 
    if(info.getType() == ConnectivityManager.TYPE_WIFI && info.getState() == NetworkInfo.State.CONNECTED) { 
    System.out.println("FOUND WIFI NETWORK!"); 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
    manager.bindProcessToNetwork(network); 
    } 

    app.network = network; 
    break; 
} 
} 

この

は、私が使用しているコードの一部です。しかし、私はこのタイプ

W/System.err: java.net.SocketException: Binding socket to network 586 failed: EPERM (Operation not permitted) 
W/System.err:  at android.net.Network.bindSocket(Network.java:362) 
W/System.err:  at android.net.Network.bindSocket(Network.java:331) 
W/System.err:  at android.net.Network$NetworkBoundSocketFactory.createSocket(Network.java:182) 
W/System.err:  at com.android.okhttp.internal.http.SocketConnector.connectRawSocket(SocketConnector.java:155) 
W/System.err:  at com.android.okhttp.internal.http.SocketConnector.connectCleartext(SocketConnector.java:67) 
W/System.err:  at com.android.okhttp.Connection.connect(Connection.java:152) 
W/System.err:  at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:185) 
W/System.err:  at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
W/System.err:  at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341) 
W/System.err:  at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330) 
W/System.err:  at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248) 
W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437) 
W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) 
W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:245) 
W/System.err:  at com.mypkg.myapp.utils.HttpRequestBackground.doInBackground(HttpRequestBackground.java:90) 
W/System.err:  at com.mypkg.myapp.utils.HttpRequestBackground.doInBackground(HttpRequestBackground.java:38) 
W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:295) 
W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
W/System.err:  at java.lang.Thread.run(Thread.java:818) 
W/System.err: Caused by: android.system.ErrnoException: Binding socket to network 586 failed: EPERM (Operation not permitted) 

の例外何かを取得しています。これらは、私はかなりここで間違っているものを理解していないよマニフェスト

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

で宣言されたネットワーク関連の権限あります。

これは、データが有効になっていて、接続されているAPにインターネットが搭載されていない場合、Androidは私のアプリでWi-Fi接続を使用できません。

答えて

1

問題は、バックグラウンドで実行されていたVPNアプリケーションが原因であることが判明し、以前は動作していたようなOkHttpClientでも問題が発生していました。


解決策はOkHttpClientを使用して見つかりました。基本的にnetwork.openConnectionが使用されている場合は、おそらくあなたがrootでない限り、< 1024というポートにバインドしようとすると、何らかのバグがあります。

network.getSocketFactory()を実行してOkHttpClientに渡しても、それは正常に機能します。

は、ここで私がテストに使用されるコードの一部です:

package com.nileshgr.networktest; 

import android.net.ConnectivityManager; 
import android.net.Network; 
import android.net.NetworkCapabilities; 
import android.net.NetworkRequest; 
import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 

import java.io.IOException; 

import okhttp3.Call; 
import okhttp3.Callback; 
import okhttp3.OkHttpClient; 
import okhttp3.Request; 
import okhttp3.Response; 

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     NetworkRequest.Builder requestbuilder = new NetworkRequest.Builder(); 
     requestbuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 

     ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); 

     cm.requestNetwork(requestbuilder.build(), new ConnectivityManager.NetworkCallback() { 
      @Override 
      public void onAvailable(Network network) { 
       System.out.println("wifi network found"); 
       testSocket(network); 
      } 
     }); 
    } 

    private void testSocket(Network network) { 

     // client one, should go via wifi 
     OkHttpClient.Builder builder1 = new OkHttpClient.Builder(); 
     builder1.socketFactory(network.getSocketFactory()); 
     OkHttpClient client1 = builder1.build(); 
     Request request1 = new Request.Builder().url("http://text.whatisyourip.org").build(); 

     Callback cb = new Callback() { 
      @Override 
      public void onFailure(Call call, IOException e) { 
       e.printStackTrace(); 
      } 

      @Override 
      public void onResponse(Call call, Response response) throws IOException { 
       System.out.println("success"); 
       System.out.println(response.body().string()); 
      } 
     }; 

     System.out.println("sending via wifi network"); 

     client1.newCall(request1).enqueue(cb); 

     System.out.println("Sending via data network"); 

     // client 2 should go via data 
     OkHttpClient client2 = new OkHttpClient(); 
     Request request2 = new Request.Builder().url("http://text.whatisyourip.org").build(); 
     client2.newCall(request2).enqueue(cb); 
    } 
} 

あなたはadbのログに2つの異なるパブリックIPアドレスが表示されます - 1お使いの無線LANのパブリックIPアドレスやその他のデータのパブリックIPアドレス。しかし、あなたが接続されている無線LANネットワークで、text.whatsiyourip.orgだけを許可し、他のすべてをブロックするようにしてください。あなたが複数のSSIDサポートとファイアウォールを持つルータを持っているなら、それはかなり簡単です。

関連する問題