Android'de WIFI Bağlantısının ne zaman kurulduğunu nasıl tespit edebilirim?


140

WIFI üzerinden ağ bağlantım olduğunda ne yapmam gerektiğini tespit etmeliyim. Geçerli bir ağ bağlantısının kurulduğunu belirlemek için hangi yayın gönderilir. HTTP için geçerli bir ağ bağlantısı olduğunu doğrulamam gerekiyor. Geçerli bir bağlantının var olduğunu bilmek için ne dinlemeliyim ve hangi ek testlere ihtiyacım var?


Bu sorunun bazı kısımları burada cevaplandırıldı: stackoverflow.com/questions/4238921/…
Androider

1
Ama hala bu koşulları NE ZAMAN kontrol etmek gerekir?
Androider

1
Bir yayın alıcısı tarafından yakalanabilecek yayınlar olup olmadığı hakkında geri bildirim almak isterim?
Androider

1
Android.net'te bunu android.net.wifi.STATE_CHANGE gibi örtülü yayın alıcılarının artık manifest'e kaydetmesine izin verilmeyeceği için nasıl yapabilirim (bkz. Developer.android.com/guide/components/… ). Uygulama etkinliğine (diyelim ki onCreate) kaydettirirsek, onStop () 'da kaydının silinmesi gerekecektir ve artık wifi ile ilgili etkinlikler almayacağız
zafar142003

Yanıtlar:


126

BroadcastReceiverBir WiFi bağlantısı kurulduğunda (veya bağlantı değiştiğinde) haberdar olmak için a kaydedebilirsiniz .

Kayıt olun BroadcastReceiver:

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

Ve sonra BroadcastReceiverböyle bir şey yapın:

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

Daha fazla bilgi için BroadcastReceiverveWifiManager

Tabii ki cihazın bundan önce WiFi'ye zaten bağlı olup olmadığını kontrol etmelisiniz.

EDIT: Ban-geoengineering sayesinde, cihazın zaten bağlı olup olmadığını kontrol etmek için bir yöntem:

private boolean isConnectedViaWifi() {
     ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
     NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
     return mWifi.isConnected();
}

1
Neden SUPPLICANT_CONECTION_CHANGE_ACTION? SADECE CONNECTION_CHANGE değişiklik yayını olduğunu düşündüm. Neden TEDARİKÇİ ??? teşekkürler
Androider

2
ha? Connection_change adlı bir eylem görmüyorum ...? Ben sadece wifi devlet değişti görmek ama bu eylem sadece wifi etkin olup olmadığını gösterir (veya en- / devre dışı) bağlı değil ... supplicant_connection_change_action ihtiyacınız olan şeyi yapmıyor?
jpm

9
Benim için WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION bilinen bir wifi istasyonuna bağlantı kurulduğunda / kaybolduğunda çalışmaz. Ancak WifiManager.NETWORK_STATE_CHANGED_ACTION çalışıyor.
Yar

1
"android.net.wifi.STATE_CHANGE" benim için çalıştı. cevabımı aşağıda görebilirsiniz
M. Usman Khan

1
"Tabii ki cihazın bundan önce WiFi'ye zaten bağlı olup olmadığını kontrol etmelisiniz." - yani, ilk Wi-Fi durumunu almak için bu yöntemi kullanabilirsiniz ...private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
ban-geoengineering

106

Benim için en iyisi:

AndroidManifest

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

BroadcastReceiver sınıfı

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

İzinler

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

1
Bu özellikle wifi devlet chage için en iyi cevap olduğunu düşünüyorum. Teşekkürler
Mikel


3
if (info! = null && info.isConnected ()) = spagetti yok.
gswierczynski

1
ana faaliyette yayın göndermek için herhangi bir kod yazmamız gerekiyor mu?
Nisari Balakrishnan

1
Android.net'te bunu android.net.wifi.STATE_CHANGE gibi örtülü yayın alıcılarının artık manifest'e kaydetmesine izin verilmeyeceği için nasıl yapabilirim (bkz. Developer.android.com/guide/components/… ). Uygulama etkinliğine (diyelim ki onCreate) kaydettirirsek, onStop () 'da kaydının silinmesi gerekecektir ve artık wifi ile ilgili etkinlikler almayacağız.
zafar142003

18

Benim için sadece WifiManager.NETWORK_STATE_CHANGED_ACTIONçalışıyor.

Bir yayın alıcısını kaydedin:

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

ve al:

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

1
Benim için de sadece WifiManager.NETWORK_STATE_CHANGED_ACTION çalıştı, bunun sadece neden işe yarayacağına dair herhangi bir açıklama var mı?
benchuk

11

@JPM ve @usman tarafından verilen cevap gerçekten çok kullanışlıdır. İyi çalışıyor ama benim durumumda onReceivebenim durumumda 4 kez birden çok kez geliyor, bu yüzden kodum birden çok kez yürütür.

Ben bazı değişiklikler yapmak ve benim şartının gibi yapmak ve şimdi sadece 1 kez geliyor

İşte yayın için java sınıfı.

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

    }
}
}

Android'deManifest

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

1
wifiState nedir?
behelit

1
Ayrıca wifiState'in nasıl olduğunu, nasıl oluşturulduğunu bilmek ister misiniz
Evan Parsons

1
@behelit şimdi "wifiState" düzenlenmiş cevap var.
Yog Guru

8

Sen edebilirsiniz sen her seferinde kullanıcının soran normal davranışını geçersiz kılmak için bir seçenek sunmak eğer bir wifi bağlantısı başlatın.

Üç yöntem kullanmayı tercih ediyorum ...

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

Bu, bir kablosuz bağlantı Wifi veya CellData olup olmadığını hızlı bir şekilde kontrol eder. Buradan hangi eylemi yapmak istediğinizi seçebilirsiniz. Uçak modunda mı da kontrol edilmesi gerekiyor.

Ayrı bir iş parçacığında. Değişken bir IpAddress = "" olarak ayarladım ve geçerli bir IP adresi olana kadar yoklama.

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

Başka bir kod snippet'i ... Açık değilse (kullanıcıların önceden izniyle)

   if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);  

7

WIFI bağlantı durumunu algılamak için, ConnectivityManager sınıfından CONNECTIVITY_ACTION kullandım:

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

ve BroadCastReceiver'ınızdan:

    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: benim için iyi çalışıyor :)


1
fyi, geçerli bir hücre veri bağlantınız olduğunda Android 6 ile wifi durumundaki değişiklikler CONNECTIVITY_ACTION'ı tetiklemez. Yapmalarının tek nedeni bağlantı durumunun etkilenmesiydi, şimdi değil.
Bruce

5

Bu kod hiç izin gerektirmez. Yalnızca Kablosuz ağ bağlantı durumu değişiklikleriyle sınırlıdır (başka herhangi bir ağ dikkate alınmaz). Alıcı statik AndroidManifest.xml dosyasında yayınlanan ve sistem tarafından çağrılır olarak dışa gerekmez protected broadcast, NETWORK_STATE_CHANGED_ACTIONher ağ bağlantısı durumu değişikliği de.

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>

BroadcastReceiver sınıfı:

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

İzinler:

None

1
<API 26 çalıştıran cihazlarda çalışıyor. @Isham'ın eylemin Android O'da artık desteklenmediğini belirtti
tiagocarvalho92

3

İşte benim kod, kullanıcıların sadece Wifi bağlı olduğunda comms izin tercih tercih dikkate bir örnek.

Bir IntentServiceşey indirmeye çalışmadan önce bir içten bu kodu arıyorum .

Herhangi bir ağ bağlantısı yoksa bunun NetworkInfoolacağını unutmayın null.

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

3

Android O, bir wifi durumu değişikliği için örtük yayınları alma olasılığını kaldırdı. Dolayısıyla uygulamanız kapalıysa, bunları alamazsınız. Yeni WorkManager, uygulamanız kapandığında çalışma yeteneğine sahip, bu yüzden biraz denedim ve oldukça iyi çalışıyor gibi görünüyor:

Bunu bağımlılıklarınıza ekleyin:

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

Bunun bir kerelik bildirim için hızlı bir test olduğunu unutmayın. WiFi açıldığında ve kapatıldığında her zaman bildirim almak için yapılacak daha fazla iş var.

Not: Uygulama zorla bırakıldığında , çalışan başlatılmaz, o WorkManagerzaman istekleri iptal ediyor gibi görünüyor .


Benim app zorla devlet devlet olsa bile işçi başlatmak için herhangi bir yolu var mı. Work manager yalnızca uygulama açıksa .setRequiredNetworkType (UNMETERED) ile çalışıyor. Uygulamayı öldürmek bile işçi tetiklemek için herhangi bir yolu var mı (kapalı güç kapalı). Çünkü örtülü geniş alıcı alıcı da biraz kısıtlanmış. En iyi alternatif ne olacak?
Suresh

2

Bu kodu kullandım:

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

2

Uygulama bağlamını alan WIFI bağlantısını tespit etmek için iki yöntemim var:

1) Eski yöntemim

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) Yeni yöntemim (şu anda bu yöntemi kullanıyorum):

public boolean isConnectedWifi(Context context) {
         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);     
         return networkInfo.isConnected();
}

Android.net'te bunu android.net.wifi.STATE_CHANGE gibi örtülü yayın alıcılarının artık manifest'e kaydetmesine izin verilmeyeceği için nasıl yapabilirim (bkz. Developer.android.com/guide/components/… ). Uygulama etkinliğine (diyelim ki onCreate) kaydettirirsek, onStop () 'da kaydının silinmesi gerekecektir ve artık wifi ile ilgili etkinlikler almayacağız
zafar142003 3:18


2

1) CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE'ın API 28'de kullanımdan kaldırıldığını ve önerilmediğini bildiğim halde Yayın Alıcısı yaklaşımını da denedim . Ayrıca açık kayıt kullanmaya da bağlıdır, uygulama çalıştığı sürece dinler.

2) Ayrıca çalışan ancak uygulamanın ötesinde değil Firebase Dispatcher denedim.

3) Önerilen yöntem WorkManager'ın registerNetworkRequest () kullanılarak öldürülen ve dahili olarak prosesin ötesinde yürütülmesini garanti etmesidir.

# 3 yaklaşımı lehine en büyük kanıt Android doc tarafından belirtilmiştir . Özellikle arka plandaki uygulamalar için.

Ayrıca burada

Android 7.0'da, yaygın olarak kullanılan üç gizli yayını kaldırıyoruz - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE ve ACTION_NEW_VIDEO - bunlar birden fazla uygulamanın arka plan işlemlerini aynı anda uyandırabilir ve belleği ve pili azaltabilir. Uygulamanız bunları alıyorsa, bunun yerine JobScheduler ve ilgili API'lara geçmek için Android 7.0'dan yararlanın.

Şimdiye kadar Periyodik WorkManager isteğini kullanarak bizim için iyi çalışıyor.

Güncelleme: Bu konuda 2 seri orta yazı yazdım .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.