[Android] كيفية التحقق من الوصول إلى الإنترنت على الروبوت؟ InetAddress لم أوقات الخروج


Answers

اتصال الشبكة / الوصول إلى الإنترنت

  • isConnectedOrConnecting() (يستخدم في معظم الإجابات) يتحقق لأي اتصال بالشبكة
  • لمعرفة ما إذا كان أي من هذه الشبكات لديه اتصال بالإنترنت ، استخدم أحد ما يلي

أ) اختبار خادم (سهل)

// 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 ، وما إلى ذلك) ، فإنه يمنع بعض الوقت إذا لم يتوفر الإنترنت

ب) الاتصال بمقبس على الإنترنت (متقدم)

// 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; }
}

+ سريع جدا (في كلتا الحالتين) ، يعمل على جميع الأجهزة ، موثوقة للغاية

~ لا يمكن تشغيلها على مهمة واجهة المستخدم

- لا شيء

هذا يعمل بشكل موثوق به للغاية ، على كل جهاز ، وهو سريع جدا. تحتاج إلى تشغيل في مهمة منفصلة على الرغم من (مثل ScheduledExecutorService أو AsyncTask ).

أسئلة محتملة

  • هل هو سريع حقا بما فيه الكفاية؟

    نعم ، سريع جدا ؛-)

  • ألا توجد طريقة موثوقة للتحقق من الإنترنت ، بخلاف اختبار شيء ما على الإنترنت؟

    ليس بقدر ما أعرف ، ولكن اسمحوا لي أن أعرف ، وسأقوم بتحرير جوابي.

  • ماذا لو كان DNS معطلاً؟

    Google DNS (على سبيل المثال 8.8.8.8 ) هو أكبر DNS عام في العالم. اعتبارا من عام 2013 كان يخدم 130 مليار طلب في اليوم. دعنا نقول فقط ، من المحتمل ألا يكون تطبيقك هو حديث اليوم.

  • ما الأذونات المطلوبة؟

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

    مجرد الوصول إلى الإنترنت - مفاجأة ^^ (هل فكرت يومًا ، كيف يمكن لبعض الطرق المقترحة هنا أن تحتوي على غراء بعيد عن الوصول إلى الإنترنت ، بدون هذا الإذن؟)

إضافي: One-shot 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 */ });
Question

حصلت على 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();
    }   
}






الإجابات الأخرى التي تستخدم ConnectivityManager خاطئة لأن وجود اتصال بالشبكة لا يعني أن لديك اتصالاً بالإنترنت. على سبيل المثال ، قد يكون المستخدم متصلاً بمنفذ WiFi في المقهى ولكن لا يمكنه الوصول إلى الإنترنت. للتحقق من إمكانية الوصول إلى الإنترنت ، عليك محاولة الاتصال بخادم فعلي. عندما تريد أن تفعل ذلك عادةً ما تضع في اعتبارك خادمًا معينًا ترغب في الاتصال به ، فانتقل أولاً وتحقق مما إذا كان يمكنك الاتصال بهذا الخادم. إليك طريقة بسيطة للتحقق من الاتصال بالخادم.

private boolean isOnTheInternet() {
    try {
        URLConnection urlConnection = new URL("http://yourserver").openConnection();
        urlConnection.setConnectTimeout(400);
        urlConnection.connect();
        return true;
    } catch (Exception e) {
        return false;
    }
}

السبب في تعيين ConnectTimeout هو أنه بخلاف ذلك الافتراضي إلى TCP مهلة التي يمكن أن تكون طويلة عدة ثوان.

لاحظ أيضًا أن Android لن يسمح لك بتشغيل هذا على مؤشر الترابط الرئيسي الخاص بك.




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

}



There's more than one way

First, shortest but Inefficient way

Network State Permission only needed

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

Then this method,

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

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

        return isConnected;

    }

As seen in answers ConnectivityManager is a solution, I just added it within a method this is a simplified method all use
ConnectivityManager returns true if there is a network access not Internet access, means if your WiFi is connected to a router but the router has no internet it returns true, it check connection availability

Second, Efficient way

Network State and Internet Permissions needed

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

Then this class,

 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
            }

        }


    }

Call CheckInternetAsyncTask

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

Some Explanations :-

  • you have to check Internet on AsyncTask , otherwise it can throw android.os.NetworkOnMainThreadException in some cases

  • ConnectivityManager used to check the network access if true sends request (Ping)

  • Request send to http://clients3.google.com/generate_204 , This well-known URL is known to return an empty page with an HTTP status 204 this is faster and more efficient than http://www.google.com , read this . if you have website it's preferred to put you website instead of google, only if you use it within the app

  • Timeout can be changed range (20ms -> 2000ms), 1500ms is commonly used




الدردشة باستخدام هذا الرمز بدلا من 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();
    }



أفضل نهج:

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

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



إلقاء نظرة على فئة 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) 

و تحليل التعداد DetailedState للكائن NetworkInfo الذي تم إرجاعه

تحرير 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();



يمكنك التكرار عبر جميع اتصالات الشبكة والشيخ ما إذا كان هناك اتصال واحد متوفر على الأقل:

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



إنه يعمل بالنسبة لي. حاول.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://.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());
}}



للحصول على getActiveNetworkInfo() للعمل تحتاج إلى إضافة ما يلي إلى البيان.

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



كل شيء رأيته حتى الآن أقصر وأقصر طريقة يجب أن يكون:

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

ملاحظة: هذا لا يتدخل بين أي مضيف ، إنه يقوم فقط بفحص connectstatus ، لذلك إذا كان جهاز التوجيه الخاص بك لا يوجد به اتصال بالإنترنت وكان جهازك متصلاً به ، فإن هذه الطريقة ستعود على الرغم من عدم وجود الإنترنت.
للحصول على اختبار فعلي ، أوصي بتنفيذ طلب HttpHead (على سبيل المثال إلى www.google.com) وتحقق من الحالة ، إذا كان كل شيء على ما يرام 200 على ما يرام وكان جهازك يحتوي على اتصال بالإنترنت.




لقد صنعت هذا الكود ، إنه أبسط وهو مجرد منطقي. من خلال السؤال عما if(isOnline()){

تحصل إذا كان هناك اتصال وإذا كان يمكن الاتصال على صفحة رمز الحالة 200 (اتصال مستقر).

تأكد من إضافة أذونات INTERNET و ACCESS_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;
}



public boolean isOnline() {
    boolean var = false;
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if ( cm.getActiveNetworkInfo() != null ) {
        var = true;
    }
    return var;
} 

I have done it this way. A little bit shorter and more readable I guess.

في صحتك!

Saiyan




Update 29/06/2015 If you are using Xamarin.Android and want to check for connectivity, you can use a Nuget package that would give you this functionality on multiple platforms. Good candidates are here and here . [End of Update]

The Answers above are quite good, but they are all in Java, and almost all of them check for a connectivity. In my case, I needed to have connectivity with a specific type of connection and I am developing on Xamarin.Android. Moreover, I do not pass a reference to my activities Context in the Hardware layer, I use the Application Context. So here is my solution, in case somebody comes here with similar requirements. I have not done full testing though, will update the answer once I am done with my testing

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
    }





Links