Androidでインターネットアクセスを確認する方法 InetAddressがタイムアウトすることはありません


658

AsyncTaskホスト名へのネットワークアクセスをチェックするはずのを取得しました。しかし、doInBackground()タイムアウトすることはありません。誰か手がかりはありますか?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}

5
インターネット接続を確認するには、おそらく最も信頼できる方法は、主要なネームサーバーの1つにpingすることif(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) ...です。これは、たとえばを使用して行うことができます。これのより良い実装については私の答えを見ください。受け入れられた答え(そしてここで他の多くの他)は、インターネットではなく、ネットワーク接続を確認するだけです。
Levite 2014


4
pingメソッドを使用せず、代わりにHTTPチェックを使用してください。一部のネットワークではICMPがブロックされているため、pingは機能しません。例:自宅のWi-Fiでは完全に機能しますが、ボーダフォンのネットワーク(ハンガリー)でモバイルデータを使用している場合は機能しません。または、2つのメソッドをフォールバックとして組み合わせますが、waitFor()は-wまたは-Wが使用されている場合でも約20秒待機するので注意してください。
タマシュBolvári

これをチェックしてください:stackoverflow.com/a/39766506/3806413
0xAliHn

@TamásBolvári:tcpレイヤーで取り組むのがさらに良いでしょう。HTTPリクエストの信頼性により、ICMPの速度に近づくはずです。「ping回答」を適宜編集しました。
Levite 2017

回答:


555

ネットワーク接続/インターネットアクセス

  • isConnectedOrConnecting()(ほとんどの回答で使用されます)ネットワーク接続をチェックします
  • これらのネットワークのいずれかにインターネットアクセスがあるかどうかを確認するには、次のいずれかを使用します

A)サーバーへのping(簡単)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}

+ メインスレッドで実行できます

- 一部の古いデバイス(Galays S3など)では機能しません。インターネットが利用できない場合はしばらくブロックされます。

B)インターネット上のソケットに接続する(上級)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}

+非常に高速(どちらの方法でも)、すべてのデバイスで動作し、非常に信頼性が高い

- UIスレッドでは実行できません

これは、すべてのデバイスで非常に確実に機能し、非常に高速です。ただし、別のタスクで実行する必要があります(例:ScheduledExecutorServiceまたはAsyncTask)。

考えられる質問

  • 本当に十分速いですか?

    はい、非常に高速です;-)

  • インターネットで何かをテストする以外に、インターネットをチェックする信頼できる方法はありませんか?

    私の知る限りではありませんが、お知らせください。回答を編集します。

  • DNSがダウンしている場合はどうなりますか?

    Google DNS(例8.8.8.8:)は、世界最大のパブリックDNSです。2013年の時点で、1日に1,300億のリクエストを処理しました。ただ、あなたのアプリはおそらく今日の話ではないでしょう。

  • どの権限が必要ですか?

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

    ただのインターネットアクセス-サプライズ^^(ところで、ここで提案されている方法のいくつかは、この許可なしに、インターネットアクセスについてリモートの接着剤を使用することさえできると思いますか?)

 

追加:ワンショットのAsyncTask

class InternetCheck extends AsyncTask<Void,Void,Boolean> {

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });

Extra:ワンショットのRxJava/RxAndroid例(Kotlin)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)

      socket.connect(socketAddress, timeoutMs)
      socket.close()

      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

///////////////////////////////////////////////////////////////////////////////////
    // Usage

    hasInternetConnection().subscribe { hasInternet -> /* do something */}

22
これはコードの平和です!プリペイドカードを使用するデバイスでは非常に便利です。彼らがお金を使い果たすとき、彼らは利用可能なインターネットアクセスを持っていますが、インターネットはありません。したがって、接続を確認するだけでは機能しません。ありがとうございました!
Blejzer、2015年

10
あなたはUIでそれを実行するべきではありませんので、theradこのアプローチはブロック1である点に注意してください
セルギ

36
@Levitこれは受け入れられる答えであるはずです。上記の答えは、単にネットワークをチェックするだけで、インターネット接続ではありません。はい、これは非常に高速です。ありがとう。したがって、賛成票を投じます。
Roon13

9
このソリューションは、すべてのデバイスで機能するわけではありません。@Salmaanが述べたように、一部のデバイスは常に2を返します。テストしたデバイスにはインターネット接続があり、pingターゲットはpingリクエストに応答しているGoogle DNSサーバーです。一部のベンダーはpingリクエストを許可していないと思います。たとえば、Samsung 10.1タブレット(4.3)でテストしましたが、ソリューションが機能しません。コマンドラインユーティリティを使用してpingコマンドを実行すると、アクセス許可エラーが発生します。このコマンドは、エミュレーターでも機能しません。このソリューションの使用には注意してください。
Eren Yilmaz

9
このアプローチは、すべての電話で機能するわけではありません。たとえば、Samsung Galaxy S3では失敗します。こちらをご覧ください:pingが機能するデバイスとそうでないデバイスがあるのはなぜですか?
Adil Hussain

1032

デバイスが機内モード(またはおそらく使用可能なネットワークがない他の状況)の場合、cm.getActiveNetworkInfo()になるnullので、nullチェックを追加する必要があります。

以下変更(エディのソリューション):

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

また、次の権限をに追加しますAndroidManifest.xml

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

もう1つの小さな点として、特定の時点で絶対にネットワーク接続が必要な場合は、netInfo.isConnected()ではなくを使用する方がよい場合がありますnetInfo.isConnectedOrConnecting。ただし、これは個々のユースケース次第だと思います。


109
ネットワークが接続されているが、実際にはインターネットに接続されていないため、たとえばVPNを経由するため、実際にはインターネット接続がないため、httpタイムアウト例外を確認する必要があります。インスタンス、WI-FI接続はありますが、実際のインターネットトラフィックはありません。別の状況は、サーバーのハングオンです。これらは私が最近実行した2つの問題であり、接続マネージャはそこで助けにはなりません。
12

21
私は真夜中とピントゥに同意します。この答えは受け入れられる答えであってはなりません。インターネットに接続しているかどうかを確認することとは関係ありません。たとえば、ホテルのように電話がキャプティブポータルでWiFiネットワークに接続されている場合、この関数は誤ってtrueを返します。正解は、公衆インターネット上のサーバーにpingすることです。
ミゲル2014年

9
ルーターでインターネットが機能していないときにwifi経由でルーターに接続すると、上記のコードはtrueを返します。しかし、そうではないはずですよね?手伝ってくれませんか
MoHaN K RaJ

5
コンテキストを追加するcontext.getSystemService必要がありました。そうしないと機能しません。私はここに私の手掛かりを得たandroidhive.info/2012/07/...
フランシスココラレスモラレス

1
ネットワークの可用性を確認するための素晴らしい方法。しかし、インターネットアクセスを確認するにはどうすればよいですか?
タマシュBolvári

296

複雑である必要はありません。最も単純でフレームワークの方法は、ACCESS_NETWORK_STATE許可を使用して、接続されたメソッドを作成することです

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && 
       cm.getActiveNetworkInfo().isConnectedOrConnecting();
}

requestRouteToHost特定のホストと接続タイプ(wifi /モバイル)を念頭に置いている場合にも使用できます。

また、次のものが必要です。

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

あなたのアンドロイドマニフェストで。


82
アクティブなネットワークが利用できない場合は、cm.getActiveNetworkInfo()レベルでnullチェックを実行することをお勧めします。
Samuel

requestRouteToHost()の詳細については、stackoverflow.com / a / 11691676/1979773を参照してください
Spartako

コンテキストを追加するcontext.getSystemService必要がありました。そうしないと機能しません。私はここで手がかりを手に入れましたandroidhive.info/2012/07/…–
フランシスココラレスモラレス

9
このソリューションがWiFiホットスポットに接続している場合、このホットスポットがインターネットに接続していない場合でもtrueを返します。
Josh


63

取得するにgetActiveNetworkInfo()動作するようにあなたがマニフェストに以下を追加する必要があります。

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

これは間違いなく正解であるはずです(何が問題なのかを理解するのに時間がかかりすぎました)。
IndrekKõue、2011

2
これにはインターネットのアクセス許可は必要ありません。ACCESS_NETWORK_STATEだけです。インターネットは、デバイスの無線の状態を照会せずに、実際にリモートロケーションに接続している場合にのみ必要です。
トム・

3
あなたの答えは実際には実際の答えではなく、他の答えへの比較的小さな追加にすぎません。他のすべての答えがここになかった場合、あなたの答えは意味がありますか?あんまり。それはそれを使用する方法のコードで回答を拡張するか、回答を削除して別の回答に情報を追加する方が良いためです(評判を失うことはありません)
Tim

注意してくださいは、getActiveNetworkInfo()APIレベル29で推奨されていません
スタックオーバーフロー

46

ConnectivityManagerクラスを見てください。このクラスを使用して、ホスト上のアクティブな接続に関する情報を取得できます。http://developer.android.com/reference/android/net/ConnectivityManager.html

編集:あなたは使うことができます

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

または

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

返されたNetworkInfoオブジェクトのDetailedState列挙を解析します

EDIT EDIT:ホストにアクセスできるかどうかを調べるには、

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

言うまでもなく、私はContext.getSystemService(Context.CONNECTIVITY_SERVICE)をプロキシとして使用して言っています

ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();

確かではありませんが、これは現在どのようなネットワーク接続が使用されているかをテストするコードのようです。たとえば、WiFiを使用している場合、自宅のwifiルーターがインターネットに接続されているという保証はありません...実際にインターネット
サーバーに

1
EDIT EDITセクションに誤りがあったため、requestRouteToHost()コールを省略しました。今すぐ答えを
もう一度

requestRouteToHostは非推奨になりました。
Jahaziel 16

46

このコードを確認してください...それは私のために働いた:)

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;   
        @Override
        public void run() { 
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {      
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    } 
                    catch (Exception e) {
                    }
                } 
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) { 
                        waited += 100;
                    }
                }
            } 
            catch(InterruptedException e) {} // do nothing 
            finally { 
                if (!responded) { handler.sendEmptyMessage(0); } 
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}

次に、ハンドラーを定義します。

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }   
    }
};

...そしてテストを起動します:

isNetworkAvailable(h,2000); // get the answser within 2000 ms

3
グーグルは何がダウンしていますか?これには、特定のタスクには不要なINTERNET権限も必要です。最後に、それはデータを消費します(重要ではない場合でも)。これはまさにそのような汚物に思えます。
トム

28
@トムは公平を期すために、これがおそらく唯一の正しい答えです。他の例は、ネットワーク接続が利用可能かどうか、および/またはそのネットワークへの接続があるかどうかを示していますが、そのネットワークが実際にリモート接続(たとえばWebサイトへの接続)もできるかどうかの質問には答えないでください。したがって、これはポスターQに回答し、他の回答は回答しません
slinden77

2
@dmmhええ、残念ながら、私がAndroid APIで見たものとは異なります。おそらく単純なpingの方が良いかもしれません、stackoverflow.com / questions / 3905358 /…。本当に心配なら、pingするIPのリストを含めることもできます。Googleがダウンする可能性は非常に低いですが、Google、Bing、Yahooが同じ日にダウンする可能性はさらに低いためです。 。ただ私の考え。
トム

10
このチェックを行う意味はありません。システム時間とネットワークリソースを費やしてGoogleに接続する場合は、実際に関心のあるリソースに接続する代わりにそれらを費やした可能性があります。
ベンジャミン

16
中国ではGoogleがブロックされました!
Anthone 2014年

26

このリンクで見つかり、変更されました(!):

マニフェストファイルに少なくとも以下を追加します。

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

あなたがそれにアクセスしているなら、おそらくあなたはすでにインターネット権限を持っています。次に、接続をテストできるブール関数は次のとおりです。

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}

18

私はこのコードを作成しました。これは最も単純で、ブール値です。尋ねることによってif(isOnline()){

接続があり、ページに接続できる場合は、ステータスコード200(安定した接続)を取得します。

正しい追加してくださいINTERNETACCESS_NETWORK_STATE権限を。

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}

6
たぶん200をHttpURLConnection.HTTP_OKで置き換える必要があります
Yash

5
Googleがダウンした場合はどうなりますか?
Yauraw Gadav 2015年

12

それは私のために働きます:

ネットワークの可用性を確認するには:

private Boolean isNetworkAvailable() {
ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();}

インターネットアクセスを確認するには:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

これは、サーバーが正常に動作するかどうかを確認するための優れたソリューションです。ありがとう!
Williew 2014年

1
isOnline()はメインスレッドで実行すべきではありません。まるでWi-Fi信号はあるがインターネットがない場合と同じように、時間がかかりすぎてメインスレッドがブロックされるからです。
2015

9

複数の方法があります

まず、最短だが非効率的な方法

ネットワーク状態のアクセス許可のみが必要です

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

次に、この方法、

 public boolean activeNetwork () {
        ConnectivityManager cm =
                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }

答えに見られるように ConnectivityManagerいるのは解決策ですが、これを簡略化したメソッドに追加しました。これは、
ConnectivityManagerインターネットアクセスではなくネットワークアクセスがある場合、つまりWiFiがルーターに接続されているがルーターにインターネットがない場合、すべての使用がtrueを返します。 trueを返し、接続の可用性を確認します

第二に、効率的な方法

必要なネットワーク状態とインターネット権限

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

次にこのクラス、

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

            ConnectivityManager cm =
                    (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                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();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }

コール CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

いくつかの説明:-

  • あなたはインターネットをチェックする必要がありますAsyncTask、そうでなければそれはandroid.os.NetworkOnMainThreadExceptionいくつかのケースでスローすることができます

  • ConnectivityManager trueが要求を送信した場合にネットワークアクセスをチェックするために使用されます(Ping)

  • への要求送信http://clients3.google.com/generate_204、このよく知られているURLは、HTTPステータス204の空のページを返すことがわかっています。これhttp://www.google.com、を読むよりも高速で効率的です。あなたがウェブサイトを持っているなら、あなたがアプリ内でそれを使用する場合にのみ、あなたがグーグルの代わりにあなたにウェブサイトを置くことが好まれます

  • タイムアウトは範囲を変更できます(20ms-> 2000ms)、1500msが一般的に使用されます


2
すばらしい質問です。悲しいことですが、これ以上のポイントはありません。これは正解でなければなりません。
Jhon Fredy Trujillo Ortega

私はアンドロイドに不慣れです。しかし、これは十分にカバーされた回答であり、より多くの注目を集めます@ 7569106
Mazen Embaby

1
最善かつ完全な回答、ありがとうございます。条件がこのurlc.getResponseCode()== 200のようでなければならず、urlc.getContentLength()== 0
AREF

あなたの2番目のオプションがクラッシュする理由を知りません
nafees ahmed

アプリケーションがフリーズする
nafees ahmed

8

私がこれまで見てきたすべての最短で最もクリーンな方法は次のとおりです:

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}

PS:これはどのホストにもpingせず、接続ステータスをチェックするだけなので、ルーターにインターネット接続がなく、デバイスがそれに接続されている場合、このメソッドは trueます
実際の試験のために私はexecuding A HttpHeadリクエストをお勧めします(例:www.google.comにする)し、その場合は、状態を確認200 OKすべてがうまくされ、お使いのデバイスがインターネットに接続されています。


このメソッドをグローバルクラスに配置したかったので、このバージョンを使用して、呼び出し元のアクティビティからコンテキストを渡す必要がありました。ありがとう!
RyanG 2012年

8

これが私が使う方法です:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}

さらに、「接続されている」ことを確認してください:

public boolean isNetworkAvailable(final Context context) {
    final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}

メソッドの使用方法は次のとおりです。

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}

必要な許可:

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

https://stackoverflow.com/a/16124915/950427


7

モバイルデバイスでの1つの重要な使用例は、実際の接続が存在することを保証します。これは、モバイルユーザーがサインインする必要がある「キャプティブポータル」を使用してWifiネットワークに入るときの一般的な問題です。このブロック機能をバックグラウンドで使用して、接続が存在することを確認します。

/*
 * Not Thread safe. Blocking thread. Returns true if it
 * can connect to URL, false and exception is logged.
 */
public boolean checkConnectionHttps(String url){
    boolean responded = false;
    HttpGet requestTest = new HttpGet(url);
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 5000);
    DefaultHttpClient client = new DefaultHttpClient(params);
    try {
        client.execute(requestTest);
        responded = true;
    } catch (ClientProtocolException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
    } catch (IOException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
        e.printStackTrace();
    }
    return responded;
}

3
エンドツーエンドの接続を実際にチェックするための+1。しかし、「キャプティブポータル」の状況では、サインインしていなくても多くの人が上記のテストに合格することがわかりました。どのURLを要求しても、ログインページと200の応答が返されます。だから私は自分のドメインに存在しないことがわかっているページをヒットしようとし、404を取得していることを確認します。または、既知の既存のページをヒットし、200を取得していることを確認して、そのコンテンツを確認することもできます期待どおりであることを確認するために返されます。
GreyBeardedGeek 2013

6

すべてのネットワーク接続を反復処理して、少なくとも1つの使用可能な接続があるかどうかを確認できます。

public boolean isConnected() {
    boolean connected = false;

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

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}

6

私にとって、Activityクラスで接続状態をチェックすることは良い習慣ではありませんでした。

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

ここで呼び出す必要があります。または、アクティビティインスタンス(コンテキスト)を接続ハンドラークラスにプッシュダウンして、そこで接続状態を確認できるようにする必要があります。利用可能な接続(wifi、ネットワーク)がない場合、UnknownHostException例外をキャッチします。

JSONObject jObj = null;
Boolean responded = false;
HttpGet requestForTest = new HttpGet("http://myserver.com");
try {
    new DefaultHttpClient().execute(requestForTest);
    responded = true;
} catch (UnknownHostException e) {
    jObj = new JSONObject();
    try {
        jObj.put("answer_code", 1);
        jObj.put("answer_text", "No available connection");
    } catch (Exception e1) {}
    return jObj;
} catch (IOException e) {
    e.printStackTrace();
}

このようにして、このクラスを同じクラスの他のケースと一緒に処理できます(私のサーバーは常にjson文字列で応答します)


6

それは私にとってはうまくいきます。やってみて。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://stackoverflow.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}

現在、メインスレッドでネットワークにアクセスできないため、この回答は機能しません。
正宗白布鞋

1
APIレベル11から、これは機能しません。理由:developer.android.com/reference/android/os/…。それが機能する場合は、古いAndroidデバイスでこのコードを実行していることを意味します。(GBより前)。
正宗白布鞋

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll()。build(); StrictMode.setThreadPolicy(policy); ネットワークのメインスレッド例外を回避するために、プログラムに次の2行を追加します
selva_pollachi

わかりました、これは機能しないとは言わないでください。(古いバージョンのターゲットまたはStrictmodeのセットアップによって)機能するとは言えませんが、お勧めしません。これにより、ANRが発生しやすくなります。(httpurlconnectionのタイムアウト設定が非常に高いため)
正宗白布鞋

ya ..あなたは正しい..これも方法の1つなので、これを置いただけです。
selva_pollachi 2013年

6

この方法では、非常に速い方法(リアルタイムフィードバックの場合)または遅い方法(信頼性を必要とする1回限りのチェックの場合)を選択できます。

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}

5

私はInetAddressの代わりにこのコードを使用しています:

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("getResponseCode == 200");
            return new Boolean(true);
        }
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

IOExceptionがインターネット接続がないことを意味するかどうか、そしてそれがどれほど信頼できるかを明確にしておけばすばらしいでしょう。
Milad.Nozari

5

Androidネットワーク/インターネット接続のステータスを確認することは複雑ではありません。以下のDetectConnectionクラスは、このステータスを確認するのに役立ちます。

import android.content.Context;
import android.net.ConnectivityManager;

public class DetectConnection {
    public static boolean checkInternetConnection(Context context) {
        ConnectivityManager con_manager = (ConnectivityManager) context
                                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (con_manager.getActiveNetworkInfo() != null
            && con_manager.getActiveNetworkInfo().isAvailable()
            && con_manager.getActiveNetworkInfo().isConnected()) {
                return true;
        } else {
            return false;
        }
    }
}

詳細については、Androidネットワーク/インターネット接続ステータスを確認する方法をご覧 ください。


5

最善のアプローチ:

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

    return true;
    } catch (UnknownHostException e){
    return false;
    } catch (IOException e){
    return false;
    }
    }

1
このアプローチは好きですが、いくつか指摘する必要があります。isReachable()はブール値を返すため、tryセクションでtrueを返す代わりに、boolean connected = InetAddress.getByName( "google.com")。isReachable(3);のように実行できます。その後、接続を戻します。また、isReacheableはIOExceptionおよびIllegalArgumentException例外をスローするため、UnknownHostExceptionをIllegalArgumentExceptionに置き換え、3つ目のcatch:catch(例外E)を含めることをお勧めします。
Yash

2
しかし、isReachableは、ルート権限を必要とする可能性のあるICMPを使用し、通常、最新のシステムで実行中のサービスがないポート7を使用します。したがって、オンラインサービスへのルートを確認する最善の方法は、通常のTCPを使用することです。したがって、反対票。
Yash

5

以下は私のUtilsクラスのコードです:

public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager 
              = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

5
public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

public boolean isOnline() {
    ConnectivityManager cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null &&
                          activeNetwork.isConnectedOrConnecting();
}

}

問題を読み通さなかった他のすべてと同様に、インターネットへの接続を実際にはチェックしないため、これは問題を解決しません。ホットスポットでインターネットにアクセスできない場合でも、ローカルwifiホットスポットへの接続はtrueを返します。
Pedro Pombeiro 2014

5

この方法を使用して、ネットワークの可用性を検出できます。

public static boolean isDeviceOnline(Context context) {
        boolean isConnectionAvail = false;
        try {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return netInfo.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnectionAvail;
    }

5

@Levitが提供するソリューションを適用し、追加のHTTPリクエストを呼び出さない関数を作成しました。

エラーを解決します Unable to Resolve Host

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork == null) return false;

    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        case ConnectivityManager.TYPE_MOBILE:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        default:
            return false;
    }
    return false;
}

private static boolean isInternet() {

    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int exitValue = ipProcess.waitFor();
        Debug.i(exitValue + "");
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }

    return false;
}

次のように呼び出します

if (!isInternetAvailable(getActivity())) {
     //Show message
} else {
     //Perfoem the api request
}

4

1
しかし、そこで説明されている方法は、実際にはインターネット接続をチェックせず、接続が確立されているかどうか(インターネットにアクセスできるかどうか)をチェックするだけです。その公式ドキュメントのタイトルは本当に誤解を招くものです。
ティアゴ

2
質問への回答を提供することは、情報へのリンクを投稿することよりも優れています。リンクが切れた場合はどうなりますか?答えはありません。
Jose Llausas

4

私はすべての答えを調べましたが、最初にインターネットが利用可能かどうかを確認し、インターネットが利用可能である場合はインターネットがアクティブかどうかを確認する独自の回答を考え出しました。

アクティブなインターネット接続を確認するために必要なすべてのメソッドとクラスを含めました。

NetworkUtils.class

public class NetworkUtils {

    public static final int STATUS_CONNECTED = 0 ;

    public static boolean isInternetAvailable(Context ctx){
        ConnectivityManager cm = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public static int isInternetActiveWithPing() {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = process.waitFor();
            return exitValue;
        } catch (Exception ex) {
            return -1;
        }
    }

    public static boolean isInternetActiveWithInetAddress() {
        try {
            InetAddress inetAddress = InetAddress.getByName("www.google.com");
            return inetAddress != null && !inetAddress.toString().equals("");
        } catch (Exception ex) {
            return false;
        }
    }

    public static void displayInternetConnectionMessage(Context ctx){
        Toast.makeText(ctx, "Check Internet Connection", Toast.LENGTH_SHORT).show();
    }
}

以下のコードを使用して、インターネットがアクティブかどうかを確認できます。

 private void checkInternetConnection() {
        if (NetworkUtils.isInternetAvailable(this)) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) {
                        performNetworkingOperations();
                    } else {
                        if (NetworkUtils.isInternetActiveWithInetAddress()) {
                            performNetworkingOperations();
                        } else {
                            displayConnectionMessage();
                        }
                    }
                }
            }).start();

        } else {
            displayConnectionMessage();
        }
    }

    private void performNetworkingOperations() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Internet is Available", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void displayConnectionMessage() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                NetworkUtils.displayInternetConnectionMessage(MainActivity.this);
            }
        });
    }

NetworkUtilsのスレッド化の改善により、開発者がメソッドを誤用しないように「強制」
Ewoks

if条件を1つ余分に削除します。if((NetworkUtils.isInternetActiveWithPing()== NetworkUtils.STATUS_CONNECTED)|| NetworkUtils.isInternetActiveWithInetAddress()){//ネットワーク操作を実行} else {//エラーメッセージ}
Jawad Zeb

4

非常に我々はとの接続持っているかどうかを確認することが重要isAvailableを()ととの接続を確立することが可能である場合をisConnectedを()

private static ConnectivityManager manager;

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
}

ネットワークのアクティブなWiFiのタイプを判別できます。

public static boolean isConnectedWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
}

またはモバイルモビル

public static boolean isConnectedMobile(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}

権限を忘れないでください:

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

デバイス接続コンポーネントのすばらしい要約です。クラッシュを回避するには、try / catchステートメントでラップする必要があります。これらはエラー処理に包まれている限り、あなたはすぐにあなたがインターネットに接続しているかどうかを知っているよと同様に、ちょうど、あなたの日常のHttpURLConnectionの呼び出しを行う
ランギ

4

コトリンとコルーチン

私は、関数に置いてきViewModelています、viewModelScope。オブザーバブルLiveDataを使用して、接続に関するアクティビティを通知します。

ViewModel

 fun checkInternetConnection() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val timeoutMs = 3000
                    val socket = Socket()
                    val socketAddress = InetSocketAddress("8.8.8.8", 53)

                    socket.connect(socketAddress, timeoutMs)
                    socket.close()

                    withContext(Dispatchers.Main) {
                        _connection.value = true
                    }
                }
                catch(ex: IOException) {
                    withContext(Main) {
                        _connection.value = false
                    }
                }
            }
        }
    }
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection

アクティビティ

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }

3

インターネット接続を確認する次のクラスを作成するだけです。

public class ConnectionStatus {

    private Context _context;

    public ConnectionStatus(Context context) {
        this._context = context;
    }

    public boolean isConnectionAvailable() {
        ConnectivityManager connectivity = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }
        return false;
    }
}

このクラスには、接続ステータスのブール値を返すメソッドが含まれているだけです。したがって、簡単に言えば、メソッドがインターネットへの有効な接続を見つけた場合、戻り値はですtrue。それ以外の場合false場合、有効な接続が見つから場合です。

MainActivityの次のメソッドは、前述のメソッドからの結果を呼び出し、それに応じてアクションを実行するようユーザーに促します。

public void addListenerOnWifiButton() {
        Button btnWifi = (Button)findViewById(R.id.btnWifi);

        iia = new ConnectionStatus(getApplicationContext());

        isConnected = iia.isConnectionAvailable();
        if (!isConnected) {
            btnWifi.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    Toast.makeText(getBaseContext(), "Please connect to a hotspot",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
        else {
            btnWifi.setVisibility(4);
            warning.setText("This app may use your mobile data to update events and get their details.");
        }
    }

上記のコードで、結果がfalseの場合(したがって、インターネット接続がない場合、ユーザーはAndroid wi-fiパネルに移動し、wi-fiホットスポットに接続するように求められます。


3

2015年6月29日更新 Xamarin.Androidを使用していて、接続を確認する場合は、複数のプラットフォームでこの機能を提供するNugetパッケージを使用できます。良い候補者はここここですです。【更新終了】

上記の回答は非常に優れていますが、すべてJavaで作成されており、ほとんどすべての回答が接続性をチェックしています。私の場合、特定の種類の接続に接続する必要があり、Xamarin.Androidで開発しています。さらに、ハードウェアレイヤーのアクティビティコンテキストへの参照を渡さず、アプリケーションコンテキストを使用します。誰かが同様の要件を持ってここに来た場合に備えて、これが私の解決策です。ただし、完全なテストは行っていません。テストが終了したら、回答を更新します

using Android.App;
using Android.Content;
using Android.Net;

namespace Leopard.Mobile.Hal.Android
{
    public class AndroidNetworkHelper
    {
        public static AndroidNetworkStatus GetWifiConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Wifi);
        }

        public static AndroidNetworkStatus GetMobileConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Mobile);
        }

        #region Implementation

        private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
        {
            var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
            var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
            var result = GetNetworkStatus(wifiNetworkInfo);
            return result;
        }

        private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
        {
            var result = AndroidNetworkStatus.Unknown;
            if (wifiNetworkInfo != null)
            {
                if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
                {
                    result = AndroidNetworkStatus.Connected;
                }
                else
                {
                    result = AndroidNetworkStatus.Disconnected;
                }
            }
            return result;
        } 

        #endregion
    }

    public enum AndroidNetworkStatus
    {
        Connected,
        Disconnected,
        Unknown
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.