WiFiP2PManager、OnPeersAvailable、DeviceList.Count 为零 - 始终

Posted

技术标签:

【中文标题】WiFiP2PManager、OnPeersAvailable、DeviceList.Count 为零 - 始终【英文标题】:WiFiP2PManager, OnPeersAvailable, DeviceList.Count zero - always 【发布时间】:2020-06-05 02:17:27 【问题描述】:

我已经在 2 部运行 Xamarin 测试应用程序的三星 S8 手机上苦苦挣扎了好几天,使用最少的 WiFiP2PManager 代码来发现同行。我已经翻遍了社区论坛和文档——不可能这么难,一定有我遗漏的东西。

我检查了常见的错误:

应用权限集 (ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE, CHANGE_NETWORK_STATE, INTERNET) WiFi 直接打开了吗 两部手机是否都处于发现模式(或不同,结果相同)

尽管如此,OnPeersAvailable 还是使用 DeviceList 的空集合调用。

调试窗口中的调用顺序是:

    WifiP2pManager.Initialize MainActivity.RegisterReceiver WifiP2pManager.DiscoverPeers WifiP2pManager.RequestPeers OnPeersAvailable (DeviceList.Count == 0)

这是我的代码,也许你能看到什么?

using System;

using android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Net.Wifi.P2p;
using Android.Content;
using static Android.Net.Wifi.P2p.WifiP2pManager;

namespace WiFiDirectTest

    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity, IChannelListener, IPeerListListener
    
        private WifiP2pManager manager;
        Channel channel;
        MyBroadcastReceiver receiver;

        protected override void OnCreate(Bundle savedInstanceState)
        
            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            SetContentView(Resource.Layout.activity_main);

            System.Diagnostics.Debug.WriteLine($"Wifi - initialize");
            manager = (WifiP2pManager)GetSystemService(WifiP2pService);
            channel = manager.Initialize(this, MainLooper, null);
        


        protected override void OnResume()
        
            base.OnResume();

            System.Diagnostics.Debug.WriteLine($"Wifi - register receiver");
            receiver = new MyBroadcastReceiver(manager, channel, this);
            receiver.Register(this);

            System.Diagnostics.Debug.WriteLine($"Wifi - discover peers");
            manager.DiscoverPeers(channel, new MyActionListner());
        


        protected override void OnPause()
        
            base.OnPause();

            System.Diagnostics.Debug.WriteLine($"Wifi - unregister receiver");
            receiver.Unregister(this);
            receiver = null;
        

        public void OnPeersAvailable(WifiP2pDeviceList peers)
        
            var count = peers.DeviceList.Count;
            System.Diagnostics.Debug.WriteLine($"Wifi - peers available: count");
        

        public void OnChannelDisconnected()
        
            System.Diagnostics.Debug.WriteLine("OnChannelDisconnected");
        

        private class MyActionListner : Java.Lang.Object, WifiP2pManager.IActionListener
        
            public MyActionListner()
            
            

            public void OnFailure(WifiP2pFailureReason reason)
            
                // breakpoint placed here, never reached.
            

            public void OnSuccess()
            
            
        
    


    public class MyBroadcastReceiver : BroadcastReceiver
    
        WifiP2pManager manager;
        WifiP2pManager.Channel channel;
        MainActivity activity;

        public MyBroadcastReceiver(WifiP2pManager manager, Channel channel, MainActivity activity)
        
            this.manager = manager;
            this.channel = channel;
            this.activity = activity;
        

        public void Register(MainActivity context)
        
            var intentFilter = new IntentFilter();

            intentFilter.AddAction(WifiP2pManager.WifiP2pStateChangedAction);
            intentFilter.AddAction(WifiP2pManager.WifiP2pPeersChangedAction);
            intentFilter.AddAction(WifiP2pManager.WifiP2pConnectionChangedAction);
            intentFilter.AddAction(WifiP2pManager.WifiP2pThisDeviceChangedAction);

            context.RegisterReceiver(this, intentFilter);
        

        public void Unregister(MainActivity context)
        
            context.UnregisterReceiver(this);
        

        public override void OnReceive(Context context, Intent intent)
        
            var action = intent.Action;

            if (WifiP2pManager.WifiP2pStateChangedAction.Equals(action))
            
                 System.Diagnostics.Debug.WriteLine("WifiP2pStateChangedAction");
            
            else if (WifiP2pManager.WifiP2pPeersChangedAction.Equals(action))
            
                System.Diagnostics.Debug.WriteLine($"Wifi - request peers");
                manager.RequestPeers(channel, activity);
            
            else if (WifiP2pManager.WifiP2pConnectionChangedAction.Equals(action))
            
                System.Diagnostics.Debug.WriteLine("WifiP2pConnectionChangedAction");
            
            else if (WifiP2pManager.WifiP2pThisDeviceChangedAction.Equals(action))
            
                System.Diagnostics.Debug.WriteLine("WifiP2pThisDeviceChangedAction");
            
        
    

有什么想法吗?

-约翰

【问题讨论】:

【参考方案1】:

解决了!

原来我使用的WiFiDirectSample 是在 v6.0 (API 23) 中的新运行时权限功能之前使用旧 API 构建的。当我在我的新应用程序中模仿 WiFiP2PManager 编排时,我正在为 v9(API 28)构建。

因此,我需要在运行时明确请求权限,尽管它们已在 Android 清单中列出。我(一遍又一遍地)阅读的文档都没有提到请求权限。

        string[] permissions = 
            Manifest.Permission.AccessFineLocation,
            Manifest.Permission.AccessCoarseLocation,
            Manifest.Permission.AccessWifiState,
            Manifest.Permission.ChangeWifiState,
            Manifest.Permission.Internet
        ;
        RequestPermissions(permissions, 0);

所以我刚刚将此代码添加到我的OnCreate(),现在我在我的 OnPeersAvailable 回调中获得了同行!

【讨论】:

以上是关于WiFiP2PManager、OnPeersAvailable、DeviceList.Count 为零 - 始终的主要内容,如果未能解决你的问题,请参考以下文章

Android WifiP2pManager 发现服务超时

WifiP2pManager.requestPeers() 在 onPeersAvailable() 中不断返回旧对等点

WifiP2pManager 在 CreateGroup 上返回 BUSY 状态

如何通过 Parcelable 接口将 WifiP2pManager 对象发送到另一个活动

Android WifiP2pManager 加密/安全

Android WifiP2PManager - 几个问题