Làm cách nào để phát hiện khi kết nối WIFI được thiết lập trong Android?


140

Tôi cần phát hiện khi tôi có kết nối mạng qua WIFI. Phát sóng được gửi để thiết lập rằng một kết nối mạng hợp lệ đã được thực hiện. Tôi cần xác thực rằng tồn tại một kết nối mạng hợp lệ cho HTTP. Tôi nên lắng nghe những gì và những thử nghiệm bổ sung nào tôi cần thực hiện để biết rằng có một kết nối hợp lệ tồn tại.


Các phần của câu hỏi này đã được trả lời ở đây Tôi tìm thấy: stackoverflow.com/questions/4238921/
triệt

1
Nhưng vẫn còn câu hỏi KHI NÀO để kiểm tra các điều kiện này?
Androider

1
Tôi muốn phản hồi về việc nếu có chương trình phát sóng sẽ xảy ra có thể bị bắt bởi một người nhận phát sóng?
Androider

1
Làm cách nào tôi có thể thực hiện việc này trên Android O vì các máy thu quảng bá ngầm như android.net.wifi.STATE_CHANGE sẽ không còn được phép đăng ký trong tệp kê khai (xem developer.android.com/guide/components/ trộm ). Nếu chúng tôi đăng ký nó trong hoạt động ứng dụng (giả sử onCreate), thì nó sẽ phải được hủy đăng ký trong onStop () và chúng tôi sẽ không còn nhận được các sự kiện liên quan đến wifi
zafar142003 3/03/18

Câu trả lời:


126

Bạn có thể đăng ký BroadcastReceiverđể được thông báo khi kết nối WiFi được thiết lập (hoặc nếu kết nối thay đổi).

Đăng ký BroadcastReceiver:

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

Và sau đó trong bạn BroadcastReceiverlàm một cái gì đó như thế này:

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

Để biết thêm thông tin, xem tài liệu cho BroadcastReceiverWifiManager

Tất nhiên bạn nên kiểm tra xem thiết bị đã được kết nối với WiFi trước đó chưa.

EDIT: Nhờ ban-geengineering, đây là một phương pháp để kiểm tra xem thiết bị đã được kết nối chưa:

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

1
Tại sao SUPPLICANT_CONMENT_CHANGE_ACTION? Tôi nghĩ rằng đó là JUST CONNMENT_CHANGE thay đổi phát sóng. Tại sao lại CUNG CẤP ??? cảm ơn
Androider

2
Huh? Tôi không thấy một hành động được gọi là Connection_change ...? Tôi chỉ thấy trạng thái wifi thay đổi nhưng hành động đó chỉ cho biết liệu wifi có được bật hay không (hoặc vô hiệu hóa) không cho dù nó được kết nối ... là augicant_connection_change_action không làm những gì bạn cần?
jpm

9
Đối với tôi WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION không hoạt động trong trường hợp khi kết nối với một trạm wifi đã biết được thiết lập / mất. Nhưng WifiManager.NETWORK_STATE_CHANGED_ACTION không hoạt động.
Yar

1
"Android.net.wifi.STATE_CHANGE" đã làm việc cho tôi. kiểm tra câu trả lời của tôi dưới đây
M. Usman Khan

1
"Tất nhiên bạn nên kiểm tra xem thiết bị đã được kết nối với WiFi trước đó chưa." - vì vậy, để có được trạng thái Wi-Fi ban đầu, bạn có thể sử dụng phương pháp này ...private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
ban-geengineering

106

Điều tốt nhất đã làm việc cho tôi:

AndroidQuản lý

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

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

Quyền

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

1
Tôi nghĩ rằng đây là câu trả lời tốt nhất cho chage trạng thái wifi cụ thể. Cảm ơn
Mikel

4
Để tham khảo dễ dàng trong tương lai, hành động được mã hóa cứng đó là WifiManager.NETWORK_STATE_CHANGED_ACTION .
Anonsage

3
if (thông tin! = null && thông tin.isConnected ()) = không có spaghetti.
gswierczynski

1
chúng ta có cần viết bất kỳ mã nào để gửi phát trong hoạt động chính không ??
Nisari Balakrish Nam 6/12/2016

1
Làm cách nào tôi có thể thực hiện việc này trên Android O vì các máy thu quảng bá ngầm như android.net.wifi.STATE_CHANGE sẽ không còn được phép đăng ký trong tệp kê khai (xem developer.android.com/guide/components/ trộm ). Nếu chúng tôi đăng ký nó trong hoạt động ứng dụng (giả sử onCreate), thì nó sẽ phải được hủy đăng ký trong onStop () và chúng tôi sẽ không còn nhận được các sự kiện liên quan đến wifi.
zafar142003

18

Đối với tôi chỉ WifiManager.NETWORK_STATE_CHANGED_ACTIONhoạt động.

Đăng ký một máy thu phát sóng:

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

Và nhận:

@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
Đối với tôi cũng chỉ có WifiManager.NETWORK_STATE_CHANGED_ACTION hoạt động, bất kỳ lời giải thích nào cho lý do tại sao chỉ điều này sẽ hoạt động?
băng ghế dự bị

11

Câu trả lời được đưa ra bởi người dùng @JPM và @usman thực sự rất hữu ích. Nó hoạt động tốt nhưng trong trường hợp của tôi, nó xuất hiện onReceivenhiều lần trong trường hợp của tôi 4 lần để mã của tôi thực thi nhiều lần.

Tôi thực hiện một số sửa đổi và thực hiện theo yêu cầu của tôi và bây giờ chỉ đến 1 lần

Đây là lớp java để phát sóng.

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

    }
}
}

Trong AndroidQuản lý

<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 là gì?
xử

1
Cũng muốn biết wifiState là gì, nó được tạo ra như thế nào
Evan Parsons

1
@behelit hiện "wifiState" đã có trong câu trả lời được chỉnh sửa.
Yog Guru

8

Bạn có thể bắt đầu kết nối wifi nếu bạn cho người dùng lựa chọn ghi đè hành vi thông thường của việc hỏi mỗi lần.

Tôi chọn sử dụng ba phương pháp ...

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

Đây là kiểm tra nhanh nếu có kết nối internet hoặc Wifi hoặc CellData. Từ đây bạn có thể chọn hành động bạn muốn thực hiện. Có phải trong chế độ Máy bay cũng cần phải được kiểm tra.

Trên một chủ đề riêng biệt. Tôi đặt một biến IpAddress thành = "" Và thăm dò cho đến khi tôi có một địa chỉ IP hợp lệ.

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

Một đoạn mã khác ... Nếu nó không bật nó (với sự cho phép trước của người dùng)

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

7

Để phát hiện trạng thái kết nối WIFI, tôi đã sử dụng CONNECTIVITY_ACTION từ lớp ConnectivityManager:

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

và từ BroadCastReceiver của bạn:

    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: hoạt động tốt với tôi :)


1
fyi, với Android 6 khi bạn có kết nối dữ liệu di động hợp lệ, các thay đổi về trạng thái wifi sẽ không kích hoạt CONNECTIVITY_ACTION. Lý do duy nhất họ làm là trạng thái kết nối bị ảnh hưởng, bây giờ thì không.
Bruce

5

Mã này không cần sự cho phép nào cả. Nó chỉ bị hạn chế đối với các thay đổi trạng thái kết nối mạng Wi-Fi (bất kỳ mạng nào khác không được tính đến). Người nhận được tĩnh được công bố trên tập tin AndroidManifest.xml và không cần phải được xuất khẩu vì nó sẽ được gọi bởi hệ thống protected broadcast, NETWORK_STATE_CHANGED_ACTIONở mỗi mạng thay đổi trạng thái kết nối.

AndroidQuản lý:

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

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

Quyền:

None

1
Các hoạt động trong các thiết bị chạy <API 26. Như @Isham đề xuất hành động không còn được hỗ trợ trong Android O
tiagocarvalho92

3

Dưới đây là một ví dụ về mã của tôi, có tính đến sở thích của người dùng chỉ cho phép comms khi được kết nối với Wifi.

Tôi đang gọi mã này từ bên trong IntentServicetrước khi tôi cố tải xuống công cụ.

Lưu ý rằng NetworkInfosẽ nullkhông có kết nối mạng dưới bất kỳ hình thức nào.

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 đã loại bỏ khả năng nhận các chương trình phát sóng ngầm để thay đổi trạng thái wifi. Vì vậy, nếu ứng dụng của bạn bị đóng, bạn sẽ không thể nhận được chúng. Cái mớiWorkManager có khả năng chạy khi đóng ứng dụng của bạn, vì vậy tôi đã thử nghiệm một chút với nó và nó dường như hoạt động khá tốt:

Thêm phần này vào phần phụ thuộc của bạn:

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

ChínhActivity.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()
    }
}

Hãy nhớ rằng đây chỉ là một thử nghiệm nhanh cho thông báo một lần. Có nhiều việc phải làm để luôn được thông báo khi bật và tắt WiFi.

PS: Khi ứng dụng bị buộc thoát , công nhân không được khởi động, có vẻ như WorkManagerđang hủy các yêu cầu sau đó.


Có cách nào để bắt đầu worker ngay cả khi ứng dụng của tôi bị buộc thoát khỏi trạng thái. Trình quản lý công việc đang làm việc với .setRequiredNetworkType (UNMETERED) chỉ khi ứng dụng được mở. Có cách nào để kích hoạt worker ngay cả khi ứng dụng bị hủy (trạng thái đóng). Bởi vì người nhận diễn viên rộng rãi cũng hạn chế phần nào. Điều gì sẽ là sự thay thế tốt nhất?
Suresh

2

Tôi đã sử dụng mã này:

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

Tôi có hai phương pháp để phát hiện kết nối WIFI nhận bối cảnh ứng dụng:

1) phương pháp cũ của tôi

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) Phương thức mới của tôi (Tôi hiện đang sử dụng phương thức này):

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

Làm cách nào tôi có thể thực hiện việc này trên Android O vì các máy thu quảng bá ngầm như android.net.wifi.STATE_CHANGE sẽ không còn được phép đăng ký trong tệp kê khai (xem developer.android.com/guide/components/ trộm ). Nếu chúng tôi đăng ký nó trong hoạt động ứng dụng (giả sử onCreate), thì nó sẽ phải được hủy đăng ký trong onStop () và chúng tôi sẽ không còn nhận được các sự kiện liên quan đến wifi
zafar142003 3/03/18


2

1) Tôi cũng đã thử cách tiếp cận Trình thu phát sóng mặc dù tôi biết CONNECTIVITY_ACTION / CONNECTIVITY_CHANGE không được dùng trong API 28 và không được đề xuất. Cũng bị ràng buộc với việc sử dụng đăng ký rõ ràng, nó lắng nghe miễn là ứng dụng đang chạy.

2) Tôi cũng đã thử Firebase Dispatcher hoạt động nhưng không vượt quá ứng dụng.

3) Cách được đề xuất là WorkManager để đảm bảo thực thi vượt quá quy trình bị giết và sử dụng bên trong bằng cách sử dụng registerNetworkRequest ()

Bằng chứng lớn nhất ủng hộ cách tiếp cận số 3 được đề cập bởi chính tài liệu Android . Đặc biệt là cho các ứng dụng trong nền.

Cũng ở đây

Trong Android 7.0, chúng tôi sẽ xóa ba chương trình phát sóng ngầm được sử dụng phổ biến - CONNECTIVITY_ACTION, ACTION_NEW_PICTURE và ACTION_NEW_VIDEO - vì chúng có thể đánh thức các quá trình nền của nhiều ứng dụng cùng một lúc và làm căng bộ nhớ và pin. Nếu ứng dụng của bạn đang nhận được những thứ này, hãy tận dụng Android 7.0 để di chuyển sang JobScheduler và các API liên quan thay thế.

Cho đến nay nó hoạt động tốt đối với chúng tôi bằng cách sử dụng yêu cầu Workmanager định kỳ.

Cập nhật: Tôi đã kết thúc bằng cách viết 2 loạt bài trung bình về nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.