Android - online sprawdzanie co kilka sekund

0

Witam

Czy możecie podpowiedzieć jak sprawdzać co kilka sekund czy jestem online.
Obecnie wykonuje ping do urządzenia w LAN i na tej podstawie sprawdzam czy jest połączenie ale jednorazowo np.:

if (isConnected()) {

            if (ping()) {

                Online.setText("Online"); 

i ping

public static boolean ping() {

    String result = null;
    try {
        String ip = "192.168.0.2"; // ping address
        Process p = Runtime.getRuntime().exec("/system/bin/ping -c 1 -w 10 " + ip); // ping 3 times

        InputStream input = p.getInputStream();
        BufferedReader in = new BufferedReader(new InputStreamReader(input));
        StringBuffer stringBuffer = new StringBuffer();
        String content = "";
        while ((content = in.readLine()) != null) {
            stringBuffer.append(content);
        }

        // ping's situation
        int status = p.waitFor();
        if (status == 0) {
            result = "success";
            return true;
        } else {
            result = "failed";
        }
    } catch (IOException e) {
        result = "IOException";
    } catch (InterruptedException e) {
        result = "InterruptedException";
    } finally {
        Log.d("Ping : ", "" + result);
    }
    return false;
}
0

ja naprawdę dziwie się jak można w ogóle uważać się za programistę (nawet BARDZO początkującego) bez znajomości obsługi internetu i googla...
https://www.google.pl/search?q=java+android+internet+connection

0
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" />

ogolnie szukaj frazy android check internet connection

problem zaczyna sie z wifi, bo jestes ws tanie sprawdzic czy jest podlaczony do sieci wifi ale i tak oprocz tego musisz zrobic ping na zewnatrz zeby sprawdzic czy jest w tej sieci dostep do internetu

0

Dzięki za info ale to ogarniam
ale z tym pingiem jak zrobić aby sprawdzał ping np co 30sekund

np sprawdzenie połączeń :

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

    public Boolean isWifiConnected(){
        if(isNetworkAvailable()){
            ConnectivityManager cm
                    = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            return (cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI);
        }
        return false;
    }

    public Boolean isEthernetConnected(){
        if(isNetworkAvailable()){
            ConnectivityManager cm
                    = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            return (cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_ETHERNET);
        }
        return false;
    }
0

Musisz odpalić coś, co 30 sekund będzie uderzać w jakiś serwer np. Google (8.8.8.8) na wątku w tle. Może to być przy użyciu Service, AsyncTask, Executora, RxJavy, czy co Ci się tam podoba. Tak czy inaczej, nie będzie to niezawodne.

Niemniej, pewnie chcesz zrobić coś naookoło i to z czego powinieneś skorzystać w swoim projekcie, to WebSocket albo jeszcze lepiej gRPC. Albo inny mechanizm niż sprawdzanie czy jesteś online co 30 sekund - na przykład sprawdzanie czy masz dostęp do przynajmniej WiFi przed wykonaniem zapytania (i posiadanie natychmiastowej odpowiedzi w aplikacji) oraz obsługa błędu, gdy nie uda się osiągnąć serwera ze względu na brak dostępu do Internetu.

0

Socket do dns-a google. Zresztą sam Android tak właśnie sprawdza, dziwne że nie ma api do tego, bo sam system już wie czy naprawdę ma internet, jak nie ma to nawet pokazuje od razu ostrzeżenie, że podłączona sieć wifi nie ma internetu. Chyba, że jednak można się podłączyć pod to w swojej aplikacji.

P.S. połączenie z siecią komórkową też nie gwarantuje, że jest internet, trzeba sprawdzać socketem tak samo jak wifi. Tu też może nie być internetu albo może być captive portal

0

ok , skleiłem coś co działa np.co 3sek. ale w związku z tym iż jestem na starcie z Androidem, proszę o ewentualne uwagi co do stabilności takiego rozwiązania.

A wiec w :
onCreate daje:

if (isNetworkConnected(this)) {
           tvN.setText("Network connected");

            handler.post(refresh);

        }

--> następnie Handler:

Handler handler = new Handler();
    private final Runnable refresh = new Runnable() {
        public void run() {
            TaskIsInternetAvailable task = new TaskIsInternetAvailable();
            task.execute();
            handler.postDelayed(refresh, 3000);
        }
    };

--> AsyncTask

   private class TaskIsInternetAvailable extends AsyncTask<String, Void, Boolean> {
        protected Boolean doInBackground(String... args) {
            Boolean result = isInternetAvailable();
            return result;
        }

        protected void onPostExecute(Boolean result) {
            if (result == true) {
                Toast.makeText(MainActivity.this, String.valueOf(result), Toast.LENGTH_SHORT).show();
                tvI.setText("Internet connected");
            } else {
                Toast.makeText(MainActivity.this, String.valueOf(result), Toast.LENGTH_SHORT).show();
                tvI.setText("Internet not connected");
            }

        }
    }

--> sprawdzam połączenie.

 public static boolean isInternetAvailable() {
        String host = "www.google.com";
        int port = 80;
        Socket socket = new Socket();

        try {
            socket.connect(new InetSocketAddress(host, port), 2000);
            socket.close();
            return true;
        } catch (IOException e) {
            try {
                socket.close();
            } catch (IOException es) {}
            return false;
        }
    }
0

Z takich usprawnień na szybko AsyncTask niepotrzebnie ma String jako pierwszego generyka. Może być Void. doInBackground() i onPostExecutre() zamień na.

protected Boolean doInBackground(String... args) {
     return isInternetAvailable();
}

protected void onPostExecute(Boolean result) {
    Toast.makeText(MainActivity.this, String.valueOf(result), Toast.LENGTH_SHORT).show();
    if (result) {             
        tvI.setText("Internet connected");
    } else {
        tvI.setText("Internet not connected");
    } 
}

Jeżeli masz włączone wsparcie dla Javy 8 w Gradlu albo minimalna wspierana wersja Androida to przynajmniej 19 możesz skorzystać z kontrukcji try-with-resources do sprawdzania połączenia.

public static boolean isInternetAvailable() {
    String host = "www.google.com";
    int port = 80;
    try(Socket socket = new Socket()) {
        socket.connect(new InetSocketAddress(host, port), 2000);
        return true;
    } catch (IOException ignored) {
        return false;
    }
}

Z poważniejszych rzeczy, to masz wycieki pamięci, ponieważ nigdzie nie usuwasz callbacku z Handlera ani nie przerywasz działania AsyncTaska. Gdybyś np. obrócił ekran albo przeszedł do następnego Activity, to Twój Handler cały czas będzie działał w tle, bo nigdzie nie wywołujesz handler.removeCallbacks(refresh) i refresh będzie cały czas działać. Tutaj masz pierwszy wyciek. Drugi jest związany z samym AsyncTaskiem. Nawet gdybyś posprzątał Handler to AsyncTask mógł już być odpalony i musisz też jego przerwać w odpowiednim momencie cykly życia Activity.

Drugi problem - TaskIsInternetAvailable jest wewnętrzną klasą MainActivity. Powinieneś z tego zrobić osobną klasę, która przyjmuje w konstruktorze jakiś interfejs, który będzie konsumował wynik w onPostExecute() i reagował odpowiednio na wynik. Ten interfejs mógłbyś wtedy przekazaywać z MainActivity. Tak naprawdę najlepiej by było zamknąć Handler i AsyncTaska w jednej klasie, która by sprzątała po sobie wywołująć jedną metodę.

Po trzecie - onCreate()/onDestroy() nie są najlepszymy metodami dla tego przypadku. onStart/onStop byłyby lepsze. Dlaczego? Włącz aplikację i ją pomniejsz. Na ekranie telefonu cały czas będzie wyświetlany komunikat z Toasta, bo Handler cały czas działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1