【Settings开发】WiFi模块(二)

 

前言

    Wifi p2p是Android4.0以上用于用户之间端对端传输文件的协议,其不耗流量,且传输效率比蓝牙传输高的多。其操作流程如下:

  1. 点击进入Wifi p2p设置页,华为手机一般在WLAN页的列表中可见,OPPO手机一般在其他无线连接页的列表中。
  2. 搜索附近可连接的p2p Devices。其搜索结果会以Preference的形式添加到列表中。
  3. 在可用的Devices列表中点击发起邀请或接受另一Device发起的邀请。

    Wifi p2p主要通过WifiP2pManager来完成。

mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);

WifiP2pManager

    其api主要有:

  1. initialize,此方法必须先行被调用,用于向WifiP2p框架注册我们的应用,其方法返回值WifiP2pManager.channel决定了p2p功能是否可用。
  2. requestPeers,获取当前可用的peers(WifiP2pDevice)列表,在其PeerListListener中会已参数形式给出可用列表。
  3. discoverPeers,在p2p连接性发生变化时,比如第一次建立连接及发生disconnect时可触发此方法去初始化Peers操作。其与requestPeers不同之处在与调用时机不同,requestPeers方法主要在WIFI_P2P_PEERS_CHANGED_ACTION广播时调用。discoverPeers失败的原因可能有:ERROR(value=0,内部错误)、P2P_UNSUPPORTED(此设备不支持p2p功能)、BUSY(p2p框架繁忙中)。
  4. stopPeerDiscovery,停止扫描p2p设备。
  5. connect,通过构建Config与指定的WifiP2pDevice设备建联。
  6. setDeviceName,此为@hide的api。设置本机p2p显示名称。
  7. removeGroup,移除当前的p2p组,意为取消与相关p2p设备的连接,此方法为主动发起连接方调用。
  8. cancelConnect,取消连接,此方法为受邀请方调用。
  9. requestPersistentGroupInfo,请求曾经连接成功的p2p组。
  10. deletePersistentGroup,从系统设置里边删除曾经保存的组。

WifiP2pSettings

  • onActivityCreated

    其中监听了p2p很多状态的改变。

    //状态变化,主要指disable/enable变化
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    //可连接列表的变化监听,此为被动式监听,也可通过requestPeers主动获取peers列表
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    //Wifi p2p框架功能连接性变化的监听
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    //本机设备信息发生变化
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    //搜索变化,如搜索开始或结束的监听
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
    //被保存的曾经连接成功的group的变化
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);

    以下是广播接收者中对应action的处理。

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //状态变化,主要指disable/enable变化
            if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                //从intent中获取p2p状态
                mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,
                    WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED;
                //此处对应的是enable/disable的checkbox的变化
                handleP2pStateChanged();
            //可连接列表的变化监听
            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
                //可直接通过intent获取Peers
                mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_P2P_DEVICE_LIST);
                handlePeersChanged();
            } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
                if (mWifiP2pManager == null) return;
                NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_NETWORK_INFO);
                WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_WIFI_P2P_INFO);
                //当前p2p已经处于连接状态
                if (networkInfo.isConnected()) {
                    if (DBG) Log.d(TAG, "Connected");
                } else if (mLastGroupFormed != true) {//如果当前p2p组还没有构建
                    //start a search when we are disconnected
                    //but not on group removed broadcast event
                    //如果还没有构建group,此处就进行discoverPeers操作
                    startSearch();
                }
                mLastGroupFormed = wifip2pinfo.groupFormed;
            //设备信息变化
            } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
                if (DBG) Log.d(TAG, "Update device info: " + mThisDevice);
                //更新本机当前p2p的设备信息,如deviceName
                updateDevicePref();
            //搜索变化,如搜索开始或结束
            } else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {
                int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE,
                    WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);
                if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState);
                //如果是搜索开始则把按钮置为true
                if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {
                    updateSearchMenu(true);
                } else {
                    updateSearchMenu(false);
                }
            } else if (WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION.equals(action)) {
                if (mWifiP2pManager != null) {
                    mWifiP2pManager.requestPersistentGroupInfo(mChannel, WifiP2pSettings.this);
                }
            }
        }
    };
  • onResume

    在页面中出现时发起请求Peers,此处会在PeerListListener的回调onPeersAvailable中体现出来。

    @Override
    public void onResume() {
        super.onResume();
        getActivity().registerReceiver(mReceiver, mIntentFilter);
        if (mWifiP2pManager != null) {
            //请求获取可连接的设备
            mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this);
        }
    }
  • onPause

    对应的,在页面消失时会暂停请求Peers。

    @Override
    public void onPause() {
        super.onPause();
        if (mWifiP2pManager != null) {
            //停止扫描可连接设备信息
            mWifiP2pManager.stopPeerDiscovery(mChannel, null);
        }
        getActivity().unregisterReceiver(mReceiver);
    }
  • 主动扫描

如果用户在进入Activity后需要主动点击进行p2p设备扫描,则需调用以下方法。

    private void startSearch() {
        if (mWifiP2pManager != null && !mWifiP2pSearching) {
            mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
                public void onSuccess() {
                }
                public void onFailure(int reason) {
                    if (DBG) Log.d(TAG, " discover fail " + reason);
                }
            });
        }
    }

    在调用WifiP2pManager的discoverPeers方法后,最终会调用到WifiP2pServiceImpl中内部类P2pEnableState的processMessage去,在此方法中,首先清理掉之前的discovery请求,然后根据超时策略去进行p2pFind即设备扫描,如果p2pFind成功,则会发送PeersChanged广播与discovery成功,如失败则发送discovery失败广播。

        @Override
        public boolean processMessage(Message message) {
            if (DBG) logd(getName() + message.toString());
            switch (message.what) {
                ...
                case WifiP2pManager.DISCOVER_PEERS:
                    if (mDiscoveryBlocked) {
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                                WifiP2pManager.BUSY);
                        break;
                    }
                    // do not send service discovery request while normal find operation.
                    clearSupplicantServiceRequest();
                    if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
                        sendP2pDiscoveryChangedBroadcast(true);
                    } else {
                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                                WifiP2pManager.ERROR);
                    }
                    break;
                ...
                case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
                    WifiP2pDevice device = (WifiP2pDevice) message.obj;
                    if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
                    mPeers.updateSupplicantDetails(device);
                    sendPeersChangedBroadcast();
                    break;
                ...
                default:
                   return NOT_HANDLED;
            }
            return HANDLED;
        }
  • 弹框事件处理。

    主要分为以下三种类型的弹框事件处理:

  1. 取消连接。取消连接分为两种类型的取消,主动方取消连接还是受邀请方取消连接,此两种分别对应不同的调用方式(在本文开始介绍WifiP2pManager的api时有谈及)removeGroup以及cancelConnect。
  2. 重命名本机p2p设备名称。通过WifiP2pManager的setDeviceName传入需要修改的名称即可,其可能修改失败。底层通过SettingsProvider的Settings进行值的保存。同时设置成功会发送广播WIFI_P2P_THIS_DEVICE_CHANGED_ACTION。
        private boolean setAndPersistDeviceName(String devName) {
            if (devName == null) return false;
    
            if (!mWifiNative.setDeviceName(devName)) {
                loge("Failed to set device name " + devName);
                return false;
            }
    
            mThisDevice.deviceName = devName;
            mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
    
            Settings.Global.putString(mContext.getContentResolver(),
                    Settings.Global.WIFI_P2P_DEVICE_NAME, devName);
            sendThisDeviceChangedBroadcast();
            return true;
        }
  3. 删除group组。调用deletePersistentGroup删除成功连接过的group。
  • 用于连接的WifiP2pConfig的配置
WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = mSelectedWifiPeer.device.deviceAddress;

    int forceWps = SystemProperties.getInt("wifidirect.wps", -1);

    if (forceWps != -1) {
        config.wps.setup = forceWps;
    } else {
        if (mSelectedWifiPeer.device.wpsPbcSupported()) {
            config.wps.setup = WpsInfo.PBC;
        } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) {
            config.wps.setup = WpsInfo.KEYPAD;
        } else {
            config.wps.setup = WpsInfo.DISPLAY;
        }
    }

    mWifiP2pManager.connect(mChannel, config,
            new WifiP2pManager.ActionListener() {
                public void onSuccess() {
                    if (DBG) Log.d(TAG, " connect success");
                }
                public void onFailure(int reason) {
                    Log.e(TAG, " connect fail " + reason);
                    Toast.makeText(getActivity(),
                            R.string.wifi_p2p_failed_connect_message,
                            Toast.LENGTH_SHORT).show();
                }
        });

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值