デバイスにインターネット接続があるかどうかを確認する必要があります。次のような多くの答えを見つけました。
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
( Androidで利用可能なインターネット接続があるかどうかを検出する から取得します。)
しかし、これは正しくありません。たとえば、私がインターネットアクセスのないワイヤレスネットワークに接続しているの場合、このメソッドはtrueを返します…デバイスはインターネットに接続されており、何かにのみ接続されている場合はそうではありませんか?
あなたが正しいです。指定したコードは、ネットワーク接続があるかどうかのみをチェックします。アクティブなインターネット接続があるかどうかを確認する最良の方法は、既知のサーバーにhttp経由で接続することです。
public static boolean hasActiveInternetConnection(Context context) {
if (isNetworkAvailable(context)) {
try {
HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
urlc.setRequestProperty("User-Agent", "Test");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(1500);
urlc.connect();
return (urlc.getResponseCode() == 200);
} catch (IOException e) {
Log.e(LOG_TAG, "Error checking internet connection", e);
}
} else {
Log.d(LOG_TAG, "No network available!");
}
return false;
}
もちろん、http://www.google.com
URLを、接続したい他のサーバーに置き換えることもできます。または、稼働時間が良好であることがわかっているサーバーに置き換えることもできます。
トニー・チョーも 以下のコメント で指摘したように、このコードをメインスレッドで実行しないでください。そうしないと、NetworkOnMainThread例外が発生します(Android 3.0で)以降)。代わりにAsyncTaskまたはRunnableを使用してください。
Google.comを使用する場合は、Jeshurunの変更を確認してください。 彼の答え で、彼は私のコードを修正し、それをもう少し効率的にしました。接続する場合
HttpURLConnection urlc = (HttpURLConnection)
(new URL("http://clients3.google.com/generate_204")
.openConnection());
次に、204の応答コードを確認します
return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);
その後、最初にGoogleホームページ全体を取得する必要はありません。
THelperの答えを少し変更して、Androidが既に使用している既知のハックを使用して、接続されたWiFiネットワークにインターネットアクセスがあるかどうかを確認しました。これは、Googleホームページ全体を取得するよりもはるかに効率的です。詳細については、 here および here を参照してください。
public static boolean hasInternetAccess(Context context) {
if (isNetworkAvailable(context)) {
try {
HttpURLConnection urlc = (HttpURLConnection)
(new URL("http://clients3.google.com/generate_204")
.openConnection());
urlc.setRequestProperty("User-Agent", "Android");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(1500);
urlc.connect();
return (urlc.getResponseCode() == 204 &&
urlc.getContentLength() == 0);
} catch (IOException e) {
Log.e(TAG, "Error checking internet connection", e);
}
} else {
Log.d(TAG, "No network available!");
}
return false;
}
public boolean isInternetWorking() {
boolean success = false;
try {
URL url = new URL("https://google.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(10000);
connection.connect();
success = connection.getResponseCode() == 200;
} catch (IOException e) {
e.printStackTrace();
}
return success;
}
インターネットが実際に利用可能な場合はtrueを返します
これら2つの権限があることを確認してください
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE"/>
Lollipop以上をターゲットにしている場合、新しいNetworkCapabilitiesクラスを使用できます。
public static boolean hasInternetConnection(final Context context) {
final ConnectivityManager connectivityManager = (ConnectivityManager)context.
getSystemService(Context.CONNECTIVITY_SERVICE);
final Network network = connectivityManager.getActiveNetwork();
final NetworkCapabilities capabilities = connectivityManager
.getNetworkCapabilities(network);
return capabilities != null
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}
必ずしも完全なHTTP接続を確立する必要はありません。既知のホストへのTCP接続を開いてみて、成功した場合はインターネットに接続できます。
public boolean hostAvailable(String Host, int port) {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(Host, port), 2000);
return true;
} catch (IOException e) {
// Either we have a timeout or unreachable Host or failed DNS lookup
System.out.println(e);
return false;
}
}
次に確認してください:
boolean online = hostAvailable("www.google.com", 80);
受け入れられた回答に基づいて、メインスレッドで使用できるように、リスナーを使用してこのクラスを構築しました。
最初:バックグラウンドでインターネット接続をチェックし、その結果でリスナーメソッドを呼び出すInterntCheckクラス。
public class InternetCheck extends AsyncTask<Void, Void, Void> {
private Activity activity;
private InternetCheckListener listener;
public InternetCheck(Activity x){
activity= x;
}
@Override
protected Void doInBackground(Void... params) {
boolean b = hasInternetAccess();
listener.onComplete(b);
return null;
}
public void isInternetConnectionAvailable(InternetCheckListener x){
listener=x;
execute();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
private boolean hasInternetAccess() {
if (isNetworkAvailable()) {
try {
HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
urlc.setRequestProperty("User-Agent", "Android");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(1500);
urlc.connect();
return (urlc.getResponseCode() == 204 &&
urlc.getContentLength() == 0);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.d("TAG", "No network available!");
}
return false;
}
public interface InternetCheckListener{
void onComplete(boolean connected);
}
}
Second:メインスレッドでクラスのインスタンスをインスタンス化し、応答を待機します(AndroidのFirebase APIを使用したことがある場合は、これがよく知られているはずです!)。
new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {
@Override
public void onComplete(boolean connected) {
//proceed!
}
});
OnCompleteメソッド内で、デバイスがインターネットに接続されているかどうかを取得します。
これを試して
public class ConnectionDetector {
private Context _context;
public ConnectionDetector(Context context) {
this._context = context;
}
public boolean isConnectingToInternet() {
if (networkConnectivity()) {
try {
HttpURLConnection urlc = (HttpURLConnection) (new URL(
"http://www.google.com").openConnection());
urlc.setRequestProperty("User-Agent", "Test");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(3000);
urlc.setReadTimeout(4000);
urlc.connect();
// networkcode2 = urlc.getResponseCode();
return (urlc.getResponseCode() == 200);
} catch (IOException e) {
return (false);
}
} else
return false;
}
private boolean networkConnectivity() {
ConnectivityManager cm = (ConnectivityManager) _context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
}
マニフェストファイルに次のアクセス許可を追加する必要があります。
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE" />
<uses-permission Android:name="Android.permission.INTERNET" />
次に、そのように呼び出します:
if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
Log.d("internet status","Internet Access");
}else{
Log.d("internet status","no Internet Access");
}
接続マネージャーでwifiの種類を確認します。
//check network connection
ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean hasNetworkConnection = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
System.out.println("Connection ? : " + hasNetworkConnection);
//check wifi
boolean hasWifiConnection = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
System.out.println("Wifi ? : " + hasWifiConnection);
Androidのドキュメントでは、「TYPE_WIFI」について「WIFIデータ接続」と説明しています。デバイスは複数サポートする場合があります。」
documentation からこれを行う最新の方法は、ConnectivityManager
を使用してアクティブなネットワークを照会し、インターネット接続があるかどうかを判断することです。
public boolean hasInternetConnectivity() {
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return (activeNetwork != null &&
activeNetwork.isConnectedOrConnecting());
}
AndroidManifest.xmlファイルに次の2つの権限を追加します。
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE"/>
private static NetworkUtil mInstance;
private volatile boolean mIsOnline;
private NetworkUtil() {
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
boolean reachable = false;
try {
Process process = Java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = process.waitFor();
reachable = (returnVal==0);
} catch (Exception e) {
e.printStackTrace();
}
mIsOnline = reachable;
}
}, 0, 5, TimeUnit.SECONDS);
}
public static NetworkUtil getInstance() {
if (mInstance == null) {
synchronized (NetworkUtil.class) {
if (mInstance == null) {
mInstance = new NetworkUtil();
}
}
}
return mInstance;
}
public boolean isOnline() {
return mIsOnline;
}
上記のコードがお役に立てば幸いです。また、urアプリでインターネットの許可を得ていることを確認してください。