[解決済み] Androidでインターネット接続を確認するには?InetAddressがタイムアウトしない
質問
を取得しました。
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();
}
}
解決方法は?
ネットワーク接続/インターネット接続
-
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です。2018年現在、1日1兆件以上のクエリを処理している [... 1 ]. あなたのアプリがその日の話題になることはないでしょう。 -
どのパーミッションが必要ですか?
<uses-permission android:name="android.permission.INTERNET" />
インターネットにアクセスするだけで、驚きの効果があります^^ (ところで、ここで提案されている方法の中には、この許可なしに、インターネットアクセスについて遠隔地ののりを持つ可能性があることを、考えたことがありますか?)
おまけ ワンショット
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 */}
おまけ ワンショット
RxJava/RxAndroid
例(Java)
public static Single<Boolean> hasInternetConnection() {
return Single.fromCallable(() -> {
try {
// Connect to Google DNS to check for connection
int timeoutMs = 1500;
Socket socket = new Socket();
InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);
socket.connect(socketAddress, timeoutMs);
socket.close();
return true;
} catch (IOException e) {
return false;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
///////////////////////////////////////////////////////////////////////////////////
// Usage
hasInternetConnection().subscribe((hasInternet) -> {
if(hasInternet) {
}else {
}
});
おまけ ワンショット
AsyncTask
例
注意
これは、リクエストのやり方の別の例を示しています。しかし
AsyncTask
は非推奨なので、アプリのスレッドスケジューリング、Kotlinコルーチン、Rxなどに置き換える必要があります。
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 */ });
関連
-
スタイルが読み込まれず、ブラウザのコンソールでエラーが報告される。リソースはスタイルシートとして解釈されますが、MIMEタイプtext/htmlで転送されます。
-
java の例外が発生しました java
-
Eclipseでプロジェクトエクスプローラービューとパッケージエクスプローラービューを使う
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] Javaでネストされたループから抜け出すには?
-
[解決済み] Androidで画面の大きさをピクセル単位で取得する方法
-
[解決済み] Androidでサービスが稼働しているかどうかを確認する方法を教えてください。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
Methodのinvokeメソッド実装のJavaリフレクション
-
org.glassfish.jersey.servlet.ServletContainer
-
スレッド "main" で例外発生 java.net.BindException: アドレスは既に使用中です。NET_Bind
-
java 例外。Javaツールの初期化
-
java -serverコマンドで「Error: no `server' JVM at ... jvm.dll」を解決する方法です。
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決
-
[解決済み] Androidでインターネット接続が可能かどうかを検出する【重複】。
-
[解決済み】Androidでインターネット接続を確認する【重複あり