Android10 系统应用wifi连接和静态ip代理设置

Android10 系统应用wifi连接和静态ip代理设置

如果是Android10或者更新的Android版本wifi开发,本文对你或许有一定的帮助。

Android wifi连接和静态ip代理设置 主要针对系统应用

wifi连接的主要代码:

Android 9 以及之前的版本连接网络代码:

   // 添加一个网络并连接     
    public void addNetwork(WifiConfiguration wcg) {    
     int wcgID = mWifiManager.addNetwork(wcg);    
     boolean b =  mWifiManager.enableNetwork(wcgID, true);    
    }    
     

Android 10之后系统应用也不能使用上面这个方式连接网络了,需要下面方式:


    protected void connect(WifiConfiguration config) {
        WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
        wifiManager.connect(config, connectListener); //所有的数据都在config对象里面;connectListener 没啥作用,一般传null参数,不管密码是否正确都是回调success。
    }


无论是通过扫描找到的wifi连接还是添加的网络连接都是要调用到上面的wifiManager.connect方法。

connect方法在WifiManager中有说明:

    @hide
    @SystemApi
    @RequiresPermission(anyOf = {
            android.Manifest.permission.NETWORK_SETTINGS,
            android.Manifest.permission.NETWORK_SETUP_WIZARD,
            android.Manifest.permission.NETWORK_STACK
    })
    public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
        ...
    }

说明普通应用调不到,并且是系统api,需要一些系统权限。

WifiConfiguration对象构建

WifiConfiguration对象里面就有我们应用输入的信息比如:wifi名称,wifi密码,加密形式,是否有静态ip,是否有代理设置。

而wifi名称,wifi密码,加密形式都是相同的形式设置的,
而静态ip和代理信息相关数据是用到IpConfiguration对象进行封装。

大概需要设置的对象信息如下:

WifiConfiguration config = new WifiConfiguration();

//wifi名称
config.SSID = "XXXName";//wifi名称,一般通过扫描获取
config.networkId = "XXXId";//wifiId,非扫描的情况,比如添加wifi的情况,可以不写


//wifi加密形式,不加密的wifi,无需设置密码

//wifi密码
config.preSharedKey = "\""+Password+"\""; 
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.XXX); //加密形式,XXX为NONE/WPA_PSK/WPA_EAP
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.XXX); //验证算法,XXX为OPEN/SHARED,NONE的情况无需设置


//静态ip相关数据和代理相关数据

IpAssignment mIpAssignment = IpAssignment.DHCP;//静态配置,静态默认是:DHCP,如果是静态ip:IpAssignment.STATIC;
StaticIpConfiguration mStaticIpConfiguration = null;//静态ip,才有必要设置,否则传入null即可
ProxySettings mProxySettings = ProxySettings.UNASSIGNED; //代理情况,是否静态ip
ProxyInfo mHttpProxy = null; //代理的参数数据保存对象,无代理的情况可不用实例化,传入null即可



    //设置静态ip相关数据
    mStaticIpConfiguration = new StaticIpConfiguration();
    Inet4Address inetAddr = (Inet4Address) NetworkUtils.numericToInetAddress("ipString");//ipString为静态ip地址,NetworkUtils是系统net的工具类
    mStaticIpConfiguration.ipAddress = new LinkAddress(inetAddr, networkPrefixLength); //IP前缀长度,networkPrefixLength是0-32的数值,一般设置24
    InetAddress gatewayAddr = (Inet4Address) NetworkUtils.numericToInetAddress("gatewayIp");//gatewayIp为网关地址
    mStaticIpConfiguration.gateway = gatewayAddr;
    Inet4Address dnsAddr = (Inet4Address) NetworkUtils.numericToInetAddress("dnsString");//dns为域名地址
    mStaticIpConfiguration.dnsServers.add(dnsAddr);//域名可以添加多个,一般手机是显示可添加两个
    
    //代理设置,分为NONE无/MANUAL手动/PAC自动
    mProxySettings = ProxySettings.STATIC;//无:ProxySettings.NONE; 自动:ProxySettings.PAC
    //手动代理最为常见,需要填入三个数据:host为主机名称,port为服务器端口,exclusionList为绕过的地址(多个的情况可使用,号分隔)
    mHttpProxy = new ProxyInfo(host, port, exclusionList); 
    
    //自动代理用得不多,只需输入一个PAC网址即可:
    //Uri uri = Uri.parse("pac_ip");
    //mHttpProxy = new ProxyInfo(uri); 
    
//最后把静态ip和代理相关数据设置到IpConfiguration对象中即可
IpConfiguration ipConfiguration = new IpConfiguration(mIpAssignment,mProxySettings,mStaticIpConfiguration,mHttpProxy);
config.setIpConfiguration(ipConfiguration);

如果没有静态ip或者代理设置,可以不调用 setIpConfiguration。

这里是有很多具体判断的逻辑进行了省略,毕竟系统代码判断的逻辑太具体了,会很多。

具体代理就不贴了,太多相关条件的判断了,比如各种非空情况,看起来会比较多,比较乱。

其他

如果是普通应用,应该不能设置静态ip和代理,只能进行简单的连接;

并且Android10或者之后的版本,普通应用只能用ConnectivityManager进行连接了

同样Android10 之后,wifi开关和其他一些设置方法也是无效了,但是获取wifi开关状态,扫描wifi,获取wifi列表的方法依然正常。

如果要看为啥之前的连接方法失效,可以看看WifiServiceImp.java,里面有直接返回false的逻辑代码。

下面是Android10 普通应用输入wifi名称和密码连接的一个示例:


@RequiresApi(api = Build.VERSION_CODES.Q)
    private boolean connectAP_Q(String ssid, String pass) throws InterruptedException {

        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
                .setSsidPattern(new PatternMatcher(ssid, PatternMatcher.PATTERN_PREFIX))
                .setWpa2Passphrase(pass)
                .build();
        //创建一个请求
        NetworkRequest request = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)//创建的是WIFI网络。
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)//网络不受限
                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)//信任网络,增加这个连个参数让设备连接wifi之后还联网。
                .setNetworkSpecifier(specifier)
                .build();
        connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
               //TODO 连接OK,做些啥
            }

            @Override
            public void onUnavailable() {
               //TODO 连接失败,或者被用户取消了,做些啥
            }
        });
    }
    

发现调用之后还是要征求系统应用同意后,才能进行网络连接!

Android 10之后进行了权限收紧,导致普通应用权限更小了,wifi只是其中一个部分。

共勉:努力学习自己应该掌握的知识。

猜你喜欢

转载自blog.csdn.net/wenzhi20102321/article/details/123675077