You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在BroadcastReceiver中打开WiFi设置并实现联网提示弹窗

解决Android网络检测弹窗及跳转WiFi设置的问题

嘿,我来帮你搞定这个问题!你的BroadcastReceiver思路没问题,但有两个核心问题需要调整:直接用ApplicationContext弹AlertDialog会崩溃,以及还没实现跳转到WiFi设置的逻辑。下面一步步给你修正:

1. 修复AlertDialog的Context问题

BroadcastReceiver的onReceive里拿到的context是Application Context,而AlertDialog需要依附于Activity的Context才能正常显示。如果直接用这个context弹Dialog,会抛出android.view.WindowManager$BadTokenException异常。

解决办法是给Dialog的Window设置合适的类型,或者如果你的Receiver是动态注册在某个Activity里的,直接传入Activity的Context。这里我们处理通用场景,适配静态注册的Receiver:

2. 添加跳转到WiFi设置的逻辑

在弹窗的"确认"按钮点击事件里,创建一个跳转到系统WiFi设置界面的Intent,调用startActivity即可。需要注意的是,在Receiver中启动Activity必须添加FLAG_ACTIVITY_NEW_TASK标记。

修正后的完整BroadcastReceiver代码

public class ExampleBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            boolean noConnectivity = intent.getBooleanExtra(
                ConnectivityManager.EXTRA_NO_CONNECTIVITY, false );
            
            if (noConnectivity) {
                // 用ContextThemeWrapper适配系统主题,避免样式异常
                AlertDialog.Builder builder1 = new AlertDialog.Builder(new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light_Dialog));
                builder1.setMessage("您需要连接网络才能继续");
                builder1.setCancelable(true);
                
                // 跳转WiFi设置的按钮逻辑
                builder1.setPositiveButton(
                    "去开启WiFi", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            // 创建跳转到WiFi设置的Intent
                            Intent wifiSettingsIntent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                            // 必须添加NEW_TASK标记,Receiver中启动Activity的要求
                            wifiSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            context.startActivity(wifiSettingsIntent);
                            dialog.dismiss();
                        }
                    });
                
                // 取消按钮逻辑
                builder1.setNegativeButton(
                    "稍后再说", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
                
                AlertDialog dialog = builder1.create();
                // 设置Window类型,避免BadTokenException
                dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
                dialog.show();
            } else {
                Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

重要提醒(Android 7.0+)

从Android N(API 24)开始,系统不再允许静态注册CONNECTIVITY_ACTION广播,静态注册的Receiver将收不到网络变化的通知。如果你的应用目标版本是API 24及以上,更推荐用官方方案:

  • 动态注册BroadcastReceiver:在Activity的onCreate里注册,onDestroy里注销。
  • 或者使用ConnectivityManager.NetworkCallback(更稳定的替代方案),代码示例如下:
// 在Activity中初始化NetworkCallback
private ConnectivityManager.NetworkCallback networkCallback;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest networkRequest = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build();

    networkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            super.onAvailable(network);
            // 切换到主线程更新UI
            runOnUiThread(() -> Toast.makeText(MainActivity.this, "网络已连接", Toast.LENGTH_SHORT).show());
        }

        @Override
        public void onLost(Network network) {
            super.onLost(network);
            runOnUiThread(() -> {
                // 直接用Activity的Context弹Dialog,无异常问题
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setMessage("您需要连接网络才能继续")
                        .setPositiveButton("去开启WiFi", (dialog, which) -> {
                            Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                            startActivity(intent);
                        })
                        .setNegativeButton("稍后再说", (dialog, which) -> dialog.dismiss())
                        .show();
            });
        }
    };

    // 注册网络回调
    connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 注销回调,避免内存泄漏
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    connectivityManager.unregisterNetworkCallback(networkCallback);
}

这样调整后,你的应用就能正常检测网络状态,弹出弹窗并引导用户开启WiFi啦!

内容的提问来源于stack exchange,提问作者Jdiavec C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:47:55