Bagaimana cara mendeteksi ketika Koneksi WIFI telah dibuat di Android?

140

Saya perlu mendeteksi ketika saya memiliki konektivitas jaringan melalui WIFI. Siaran apa yang dikirim untuk memastikan bahwa koneksi jaringan yang valid telah dibuat. Saya perlu memvalidasi bahwa ada koneksi jaringan yang valid untuk HTTP. Apa yang harus saya dengarkan dan tes tambahan apa yang perlu saya lakukan untuk mengetahui bahwa ada koneksi yang valid.

Androider
sumber
Sebagian dari pertanyaan ini telah dijawab di sini yang saya temukan: stackoverflow.com/questions/4238921/…
Androider
1
Tetapi masih ada pertanyaan KAPAN memeriksa kondisi ini?
Androider
1
Saya ingin umpan balik jika ada siaran yang akan terjadi yang bisa ditangkap oleh penerima siaran?
Androider
1
Bagaimana saya bisa melakukan ini di Android O sebagai penerima siaran implisit seperti android.net.wifi.STATE_CHANGE tidak akan lagi diizinkan untuk terdaftar dalam manifes (lihat developer.android.com/guide/components/… ). Jika kami mendaftarkannya di aktivitas aplikasi (katakanlah onCreate), maka itu harus didaftarkan di onStop (), dan kami tidak akan lagi menerima acara terkait wifi
zafar142003

Jawaban:

126

Anda dapat mendaftarkan BroadcastReceiveruntuk diberi tahu ketika koneksi WiFi dibuat (atau jika koneksi berubah).

Daftarkan BroadcastReceiver:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

Dan kemudian dalam BroadcastReceivermelakukan sesuatu seperti ini:

@Override
public void onReceive(Context context, Intent intent) {
    final String action = intent.getAction();
    if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
        if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
            //do stuff
        } else {
            // wifi connection was lost
        }
    }
}

Untuk info lebih lanjut, lihat dokumentasi untuk BroadcastReceiverdanWifiManager

Tentu saja Anda harus memeriksa apakah perangkat sudah terhubung ke WiFi sebelum ini.

EDIT: Berkat larangan geoengineering, berikut adalah metode untuk memeriksa apakah perangkat sudah terhubung:

private boolean isConnectedViaWifi() {
     ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
     NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
     return mWifi.isConnected();
}
jpm
sumber
1
Mengapa SUPPLICANT_CONECTION_CHANGE_ACTION? Saya pikir itu HANYA CONNECTION_CHANGE perubahan siaran. Mengapa MENDUKUNG ??? terima kasih
Androider
2
Hah? Saya tidak melihat tindakan yang disebut connection_change ...? Saya hanya melihat kondisi wifi diubah tetapi tindakan itu hanya menunjukkan apakah wifi diaktifkan atau tidak (atau menonaktifkan) bukan apakah itu terhubung ... apakah supplicant_connection_change_action tidak melakukan apa yang Anda butuhkan?
jpm
9
Bagi saya WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION tidak berfungsi jika koneksi ke stasiun wifi yang dikenal telah dibangun / hilang. Tetapi WifiManager.NETWORK_STATE_CHANGED_ACTION tidak berfungsi.
Yar
1
"android.net.wifi.STATE_CHANGE" bekerja untuk saya. periksa jawaban saya di bawah ini
M. Usman Khan
1
"Tentu saja Anda harus memeriksa apakah perangkat sudah terhubung ke WiFi sebelum ini." - jadi, untuk mendapatkan status Wi-Fi awal, Anda dapat menggunakan metode ini ...private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
ban-geoengineering
106

Yang terbaik yang berhasil untuk saya:

AndroidManifest

<receiver android:name="com.AEDesign.communication.WifiReceiver" >
   <intent-filter android:priority="100">
      <action android:name="android.net.wifi.STATE_CHANGE" />
   </intent-filter>
</receiver>

Kelas BroadcastReceiver

public class WifiReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {

      NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
      if(info != null && info.isConnected()) {
        // Do your work. 

        // e.g. To check the Network Name or other info:
        WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        String ssid = wifiInfo.getSSID();
      }
   }
}

Izin

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
M. Usman Khan
sumber
1
Saya pikir ini adalah jawaban terbaik untuk chase keadaan wifi khusus. Terima kasih
Mikel
4
Untuk referensi mudah di masa mendatang, tindakan yang dikodekan tersebut adalah WifiManager.NETWORK_STATE_CHANGED_ACTION .
Anonsage
3
if (info! = null && info.isConnected ()) = tidak ada spageti.
gswierczynski
1
apakah kita perlu menulis kode apa saja untuk mengirim siaran dalam kegiatan utama ??
Nisari Balakrishnan
1
Bagaimana saya bisa melakukan ini di Android O sebagai penerima siaran implisit seperti android.net.wifi.STATE_CHANGE tidak akan lagi diizinkan untuk terdaftar dalam manifes (lihat developer.android.com/guide/components/… ). Jika kami mendaftarkannya di aktivitas aplikasi (misalkan onCreate), maka itu harus didaftar di onStop (), dan kami tidak akan lagi menerima acara yang terkait wifi.
zafar142003
18

Bagi saya hanya WifiManager.NETWORK_STATE_CHANGED_ACTIONberfungsi.

Daftarkan penerima siaran:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);

dan terima:

@Override
public void onReceive(Context context, Intent intent) {

    final String action = intent.getAction();

    if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
        NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
        boolean connected = info.isConnected();

        //call your method
    }      
}
Yar
sumber
1
Bagi saya juga hanya WifiManager.NETWORK_STATE_CHANGED_ACTION yang berfungsi, ada penjelasan untuk alasan mengapa hanya ini yang berfungsi?
benchuk
11

Jawaban yang diberikan oleh pengguna @JPM dan @usman benar-benar sangat berguna. Ini berfungsi dengan baik tetapi dalam kasus saya itu datang dalam onReceivebeberapa waktu dalam kasus saya 4 kali sehingga kode saya menjalankan banyak waktu.

Saya melakukan beberapa modifikasi dan membuat sesuai kebutuhan saya dan sekarang hanya 1 kali

Ini adalah kelas java untuk Siaran.

public class WifiReceiver extends BroadcastReceiver {

String TAG = getClass().getSimpleName();
private Context mContext;

@Override
public void onReceive(Context context, Intent intent) {

    mContext = context;


    if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
                networkInfo.isConnected()) {
            // Wifi is connected
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            String ssid = wifiInfo.getSSID();

            Log.e(TAG, " -- Wifi connected --- " + " SSID " + ssid );

        }
    }
    else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION))
    {
        int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
        if (wifiState == WifiManager.WIFI_STATE_DISABLED)
        {
            Log.e(TAG, " ----- Wifi  Disconnected ----- ");
        }

    }
}
}

Di AndroidManifest

<receiver android:name=".util.WifiReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </receiver>


<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Yog Guru
sumber
1
Apa itu wifiState?
behelit
1
Ingin juga tahu apa wifiState itu, bagaimana ini dihasilkan
Evan Parsons
1
@behelit sekarang "wifiState" ada di jawaban yang diedit.
Yog Guru
8

Kamu bisa memulai koneksi wifi jika Anda memberi pengguna pilihan untuk mengesampingkan perilaku bertanya yang normal setiap kali.

Saya memilih untuk menggunakan tiga metode ...

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

Ini adalah pemeriksaan cepat jika ada koneksi internet Wifi atau CellData. Dari sini Anda dapat memilih tindakan apa yang ingin Anda ambil. Apakah dalam mode Airplane perlu diperiksa juga.

Di utas terpisah. Saya mengatur variabel IpAddress ke = "" Dan polling sampai saya memiliki alamat ip yang valid.

  WifiManager wifi;
  wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
  WifiInfo wifiInfo = wifi.getConnectionInfo();
  int ipAddress = wifiInfo.getIpAddress();
  String ip = null;
  ip = String.format("%d.%d.%d.%d",
  (ipAddress & 0xff),
  (ipAddress >> 8 & 0xff),
  (ipAddress >> 16 & 0xff),
  (ipAddress >> 24 & 0xff));
  Log.e(" >>IP number Begin ",ip);

Cuplikan kode lain ... Jika tidak diaktifkan, aktifkan (dengan izin sebelumnya dari pengguna)

   if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);  
pengguna1445716
sumber
7

Untuk mendeteksi keadaan koneksi WIFI, saya telah menggunakan CONNECTIVITY_ACTION dari kelas ConnectivityManager jadi:

    IntentFilter filter=new IntentFilter();
    filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(receiver, filter);

dan dari BroadCastReceiver Anda:

    if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
        int networkType = intent.getIntExtra(
                android.net.ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
        if (ConnectivityManager.TYPE_WIFI == networkType) {
            NetworkInfo networkInfo = (NetworkInfo) intent
                    .getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            if (networkInfo != null) {
                if (networkInfo.isConnected()) {

                    // TODO: wifi is connected
                } else {
                    // TODO: wifi is not connected
                }
            }
        }

    }

ps: berfungsi baik untuk saya :)

amina
sumber
1
fyi, dengan Android 6 saat Anda memiliki koneksi data sel yang valid, perubahan status wifi tidak akan memicu CONNECTIVITY_ACTION. Satu-satunya alasan mereka melakukannya adalah keadaan konektivitas terpengaruh, sekarang tidak.
Bruce
5

Kode ini tidak memerlukan izin sama sekali. Ini dibatasi hanya untuk perubahan status konektivitas jaringan Wi-Fi (jaringan lain tidak diperhitungkan). Penerima adalah statis diterbitkan dalam file AndroidManifest.xml dan tidak perlu diekspor karena akan dipanggil oleh sistem protected broadcast, NETWORK_STATE_CHANGED_ACTION, di setiap jaringan perubahan negara konektivitas.

AndroidManifest:

<receiver
    android:name=".WifiReceiver"
    android:enabled="true"
    android:exported="false">

    <intent-filter>
        <!--protected-broadcast: Special broadcast that only the system can send-->
        <!--Corresponds to: android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION-->
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>

</receiver>

Kelas BroadcastReceiver:

public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/*
 Tested (I didn't test with the WPS "Wi-Fi Protected Setup" standard):
 In API15 (ICE_CREAM_SANDWICH) this method is called when the new Wi-Fi network state is:
 DISCONNECTED, OBTAINING_IPADDR, CONNECTED or SCANNING

 In API19 (KITKAT) this method is called when the new Wi-Fi network state is:
 DISCONNECTED (twice), OBTAINING_IPADDR, VERIFYING_POOR_LINK, CAPTIVE_PORTAL_CHECK
 or CONNECTED

 (Those states can be obtained as NetworkInfo.DetailedState objects by calling
 the NetworkInfo object method: "networkInfo.getDetailedState()")
*/
    /*
     * NetworkInfo object associated with the Wi-Fi network.
     * It won't be null when "android.net.wifi.STATE_CHANGE" action intent arrives.
     */
    NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);

    if (networkInfo != null && networkInfo.isConnected()) {
        // TODO: Place the work here, like retrieving the access point's SSID

        /*
         * WifiInfo object giving information about the access point we are connected to.
         * It shouldn't be null when the new Wi-Fi network state is CONNECTED, but it got
         * null sometimes when connecting to a "virtualized Wi-Fi router" in API15.
         */
        WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
        String ssid = wifiInfo.getSSID();
    }
}
}

Izin:

None
Codegateway
sumber
1
Bekerja di perangkat yang menjalankan <API 26. Seperti yang disarankan @Isham, tindakan tidak lagi didukung di Android O
tiagocarvalho92
3

Berikut adalah contoh kode saya, yang memperhitungkan preferensi pengguna yang hanya mengizinkan komunikasi ketika terhubung ke Wifi.

Saya memanggil kode ini dari dalam IntentService sebelum saya mencoba mengunduh barang.

Perhatikan bahwa NetworkInfoakan terjadi nulljika tidak ada koneksi jaringan apa pun.

private boolean canConnect()
{
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    boolean canConnect = false;
    boolean wifiOnly = SharedPreferencesUtils.wifiOnly();

    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    if(networkInfo != null)
    {
        if(networkInfo.isConnected())
        {
            if((networkInfo.getType() == ConnectivityManager.TYPE_WIFI) ||
               (networkInfo.getType() != ConnectivityManager.TYPE_WIFI && !wifiOnly))
            {
                canConnect = true;
            }
        }
    }

    return canConnect;
}
Justin Phillips
sumber
3

Android O menghapus kemungkinan untuk menerima siaran implisit untuk perubahan kondisi wifi. Jadi jika aplikasi Anda ditutup, Anda tidak akan dapat menerimanya. Yang baruWorkManager memiliki kemampuan untuk berjalan ketika aplikasi Anda ditutup, jadi saya telah sedikit bereksperimen dengannya dan tampaknya berfungsi dengan cukup baik:

Tambahkan ini ke dependensi Anda:

implementation "android.arch.work:work-runtime:1.0.0-alpha08"

WifiConnectWorker.kt

class WifiConnectWorker : Worker() {

    override fun doWork(): Result {
        Log.i(TAG, "I think we connected to a wifi")
        return Result.SUCCESS
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        val workManager = WorkManager.getInstance()

        // Add constraint to start the worker when connecting to WiFi
        val request = OneTimeWorkRequest.Builder(WifiConnectWorker::class.java)
            .setConstraints(Constraints.Builder()
                .setRequiredNetworkType(UNMETERED)
                .build())
            .build()

        // The worker should be started, even if your app is closed
        workManager.beginUniqueWork("watch_wifi", REPLACE, request).enqueue()
    }
}

Perlu diingat bahwa ini hanya tes cepat untuk pemberitahuan satu kali. Masih banyak pekerjaan yang harus dilakukan untuk selalu diberi tahu ketika WiFi dihidupkan dan dimatikan.

PS: Ketika aplikasi berhenti secara paksa , pekerja tidak dimulai, sepertinya WorkManagermembatalkan permintaan itu.

Marius
sumber
Apakah ada cara untuk memulai pekerja bahkan jika aplikasi saya dipaksa berhenti. Manajer kerja bekerja dengan .setRequiredNetworkType (UNMETERED) hanya jika aplikasi terbuka. Apakah ada cara untuk memicu pekerja bahkan aplikasi dalam keadaan mati (paksa ditutup). Karena penerima cast luas implisit juga agak terbatas. Apa yang akan menjadi alternatif terbaik?
Suresh
2

Saya menggunakan kode ini:

public class MainActivity extends Activity
    {
    .
    .
    .
    @Override
    protected void onCreate(Bundle savedInstanceState)
        {
        super.onCreate(savedInstanceState);
        .
        .
        .
        }

    @Override
    protected void onResume()
        {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
        registerReceiver(broadcastReceiver, intentFilter);  
        }

    @Override
    protected void onPause()
        {
        super.onPause();
        unregisterReceiver(broadcastReceiver);
        }

    private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
        {
        @Override
        public void onReceive(Context context, Intent intent)
            {
            final String action = intent.getAction();
            if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION))
                {
                if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false))
                    {
                    // wifi is enabled
                    }
                else
                    {
                    // wifi is disabled
                    }
                }
            }
        };
    }
Cuarcuiu
sumber
2

Saya punya dua metode untuk mendeteksi koneksi WIFI yang menerima konteks aplikasi:

1) metode lama saya

public boolean isConnectedWifi1(Context context) {
    try {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();           
        if (networkInfo != null) {
            NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo();
            for (NetworkInfo ni : netInfo) {
                if ((ni.getTypeName().equalsIgnoreCase("WIFI"))
                        && ni.isConnected()) {
                    return true;
                }                   
            }
        }
        return false;
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }
    return false;
}

2) Metode baru saya (Saya sedang menggunakan metode ini):

public boolean isConnectedWifi(Context context) {
         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
         return networkInfo.isConnected();
}
Jorgesys
sumber
Bagaimana saya bisa melakukan ini di Android O sebagai penerima siaran implisit seperti android.net.wifi.STATE_CHANGE tidak akan lagi diizinkan untuk terdaftar dalam manifes (lihat developer.android.com/guide/components/… ). Jika kami mendaftarkannya di aktivitas aplikasi (katakanlah onCreate), maka itu harus didaftarkan di onStop (), dan kami tidak akan lagi menerima acara terkait wifi
zafar142003
2

1) Saya juga mencoba pendekatan Penerima Siaran meskipun saya tahu CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE tidak digunakan lagi dalam API 28 dan tidak direkomendasikan. Juga terikat untuk menggunakan register eksplisit, itu mendengarkan selama aplikasi sedang berjalan.

2) Saya juga mencoba Firebase Dispatcher yang berfungsi tetapi tidak di luar aplikasi yang terbunuh.

3) Cara yang disarankan ditemukan adalah WorkManager untuk menjamin eksekusi di luar proses terbunuh dan secara internal menggunakan registerNetworkRequest ()

Bukti terbesar yang mendukung pendekatan # 3 disebut oleh Android doc itu sendiri. Khusus untuk aplikasi di latar belakang.

Juga disini

Di Android 7.0 kami menghapus tiga siaran implisit yang umum digunakan - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE, dan ACTION_NEW_VIDEO - karena mereka dapat membangunkan proses latar belakang beberapa aplikasi sekaligus dan menyaring memori dan baterai. Jika aplikasi Anda menerima ini, manfaatkan Android 7.0 untuk bermigrasi ke JobScheduler dan API terkait sebagai gantinya.

Sejauh ini berfungsi dengan baik untuk kami menggunakan permintaan WorkManager Berkala.

Pembaruan: Saya akhirnya menulis posting media 2 seri tentang hal itu.

Wahib Ul Haq
sumber