shareit 如何以编程方式发现附近的设备 android

How does shareit discovers nearby devices android programmatically

我想创建一个像 shareit 这样的文件共享应用程序,但我对 shareit 如何发现附近的设备感到很困惑。

当您点击接收按钮分享时,它会在接收方创建一个热点,而没有连接到热点的发送方会显示接收方名称。这怎么可能?

如果 shareit 直接使用 Wi-Fi,那么创建热点有什么意义?

要使用网络服务发现 (NSD),服务器和客户端都应该在同一个网络上,所以我认为 shareit 使用的是其他东西

如果有人能解释一下 shareit 的概念,那将非常有帮助。

终于找到答案了! SHAREit 使用 WiFi SSID 来识别附近的应用程序用户。 SSID 像这样由两部分组成。 BAHD-bXViYQ WHERE 'B' 代表 ANDROID 设备和用户图标的 AHD。第二部分是用Base64编码的用户名。在这个例子中我的名字是 muba。 我希望这个答案有助于节省一些时间。

好吧,我已经找到了如何从一个共享应用程序启用 hotspot 并将该共享应用程序启用的可用 wifi 列表找到另一个应用程序。就像 shareIt receiver 启用 wifi 热点和 sender discovers 可用列表 receivers。 首先,您必须使用 WifiManager

扫描所有可用的 wifi 网络
public void startScan(){
    mWifiManager.startScan();
    mScanResultList = mWifiManager.getScanResults();
    mWifiConfigurations = mWifiManager.getConfiguredNetworks();
}

现在将此 mScanResultList 传递给根据您的要求查找网络的方法。

public static List<ScanResult> filterWithNoPassword(List<ScanResult> scanResultList){
    if(scanResultList == null || scanResultList.size() == 0){
        return scanResultList;
    }

    List<ScanResult> resultList = new ArrayList<>();
    for(ScanResult scanResult : scanResultList){
        if(scanResult.capabilities != null && scanResult.capabilities.equals(NO_PASSWORD) || scanResult.capabilities != null && scanResult.capabilities.equals(NO_PASSWORD_WPS)){
            resultList.add(scanResult);
        }
    }

    return resultList;
}

现在将 resultList 传递给 arraylist 适配器以在列表中显示网络。内部适配器的 convertView 方法只是将该数据列表传递给扫描器以获取网络的 ssid 和 mac 地址

@Override
public View convertView(int position, View convertView) {
    ScanResultHolder viewHolder = null;

    if(convertView == null){
        convertView = View.inflate(getContext(), R.layout.item_wifi_scan_result, null);
        viewHolder = new ScanResultHolder();
        viewHolder.iv_device = (ImageView) convertView.findViewById(R.id.iv_device);
        viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
        viewHolder.tv_mac = (TextView) convertView.findViewById(R.id.tv_mac);
        convertView.setTag(viewHolder);
    }else{
        viewHolder = (ScanResultHolder) convertView.getTag();
    }

    ScanResult scanResult = getDataList().get(position);
    if(scanResult != null){
        viewHolder.tv_name.setText(scanResult.SSID);
        viewHolder.tv_mac.setText(scanResult.BSSID);
    }

    return convertView;
}

这是启用 hotspot

的代码
public static boolean configApState(Context context, String apName) {
    WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
    WifiConfiguration wificonfiguration = null;
    try {
        wificonfiguration = new WifiConfiguration();
        wificonfiguration.SSID = apName;
        // if WiFi is on, turn it off
        if(isApOn(context)) {
            wifimanager.setWifiEnabled(false);
            // if ap is on and then disable ap
            disableAp(context);
        }
        Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
        method.invoke(wifimanager, wificonfiguration, !isApOn(context));
        return true;
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}