Xamarin Wifi 和蓝牙伴侣配对

问题描述

编辑:将答案从问题部分移到答案部分,以便更容易理解。

我在尝试实现 Android 配套设备配对时遇到了一些问题。我仍然遇到 WiFi 配对/绑定问题。我找不到任何关于此的真实信息(我认为这不仅仅是 P2P 连接)。源文件如下所示。

Java 配对链接Android companion device pairing

Microsoft 文档链接Microsoft's documentation

我想出的答案如下,但仍然缺少用于绑定的 WiFi 组件。

解决方法

我真的找不到有关如何使用 C# Android 配套设备配对的文档。我想分享你如何实现它的一部分,而不是面对我在试图追踪和拼凑系统应该如何工作时所面临的一些挫折。如果您发现完成这些任务的更好方法,或者您知道如何完成 WiFi 绑定,请发布答案。

1)首先设置您的清单(如果使用 Visual Studio,则权限在 android 项目的属性中设置,我认为需要输入使用功能)。这份清单上的内容可能比需要的要多。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND" />
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
<uses-permission android:name="android.permission.CALL_COMPANION_APP" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-feature android:name="android.software.companion_device_setup" />
  1. 设置您的请求。在这个例子中,我包括了所有 3 种设置类型。我还没有真正弄清楚过滤器,但这至少应该让你找到正确的方向。我使方法比他们需要的更复杂,但这使我更容易阅读。内部部分可以被移除并全部放入单一方法中。 IAssociationRequest 是用于请求 MakeRequest 方法的自定义接口。

注意:我不知道这些是否是正确的活动标签。我真的找不到任何可以使用的东西,但这些确实有效。

{
    public class CompanionAssociationRequest : CompanionDeviceManager.Callback,IAssociationRequest
    {
        #region variables
        public static int SELECT_DEVICE_REQUEST_CODE = 0;
        AssociationRequest _request { get; set; }
        AssociationRequest.Builder _requestBuilder { get; set; }
        #region Bluetooth
        BluetoothDeviceFilter _filter { get; set; }
        BluetoothDeviceFilter.Builder _filterBuilder { get; set; }
        #endregion
        #region Wifi
        //WifiDeviceFilter _filter { get; set; }
        //WifiDeviceFilter.Builder _filterBuilder { get; set; }
        #endregion
        CompanionDeviceManager _companionDeviceManager { get; set; }
        CompanionDeviceManager.Callback _callback { get; set; }                
        Context _context = Android.App.Application.Context;        
        #endregion

        #region Assocaiation Request
        public async Task MakeRequest()
        {
            try
            {
                await HasNotificationAccess();
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }

            try
            {
                _companionDeviceManager = (CompanionDeviceManager)Forms.Context.GetSystemService(Context.CompanionDeviceService);                
                await Request();                
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }

            try
            {
                Console.WriteLine(_request.ToString());                
                _companionDeviceManager.Associate(_request,CompanionDeviceManagerCallback().Result,null);
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }
        }

        #endregion

        #region Filter and Request building
        private async Task Request()
        {
            try
            {
                await RequestBuilder();
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }

            try
            {
                _request = _requestBuilder.Build();
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }
        }
        private async Task RequestBuilder()
        {
            try
            {
                await Filter();
                _requestBuilder = new AssociationRequest.Builder();
                _requestBuilder.AddDeviceFilter(_filter);
                _requestBuilder.SetSingleDevice(false);

            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }            
        }
        private async Task FilterBuilder()
        {
            try
            {
                #region Bluetooth
                _filterBuilder = new BluetoothDeviceFilter.Builder();
                #endregion
                #region Wifi
                //_filterBuilder = new WifiDeviceFilter.Builder();                
                //_filterBuilder.SetNamePattern(Java.Util.Regex.Pattern.Compile(""));//I dont know if this works
                //_filterBuilder.SetBssid();                
                #endregion
                _filter = _filterBuilder.Build();
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }            
        }
        private async Task Filter()
        {
            try
            {                
                await FilterBuilder();
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }            
        }
        #endregion

        #region callback and overrides

        private async Task<CompanionDeviceManager.Callback> CompanionDeviceManagerCallback()
        {

            try
            {                
                _callback = DependencyService.Get<CompanionDeviceManager.Callback>();             
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }
            return _callback;
        }

        public override void OnDeviceFound(IntentSender chooserLauncher)
        {
            try
            {               
                DeviceSelectionRequest(chooserLauncher);
            }
            catch (Exception ex)
            {                
                Console.WriteLine(ex.StackTrace);
            }
        }

        public override void OnFailure(Java.Lang.ICharSequence error)
        {
            try
            {
                //add notification here
                Console.WriteLine("Devices not found");                      
            }
            catch (Exception ex)
            {                
                Console.WriteLine(ex.StackTrace);
            }
        }

        private void DeviceSelectionRequest(IntentSender chooserLauncher)
        {            
            try
            {
                #region activity result                
                ActivityFlags flagsMask = ActivityFlags.BroughtToFront;
                ActivityFlags flagsValues = ActivityFlags.NewTask;
                int extraFlags = 0;
                Intent fillInIntent = null;
                ((Activity)Forms.Context).StartIntentSenderForResult(chooserLauncher,SELECT_DEVICE_REQUEST_CODE,fillInIntent,flagsMask,flagsValues,extraFlags);
                #endregion   
            }
            catch (Exception ex)
            {                
                Console.WriteLine(ex.StackTrace);
            }
        }

        #endregion
                
        #region notification access
        public async Task HasNotificationAccess()
        {
            bool hasAccess = NotificationManagerCompat.From(_context).AreNotificationsEnabled();
            if (!hasAccess)
            {
                await AskForNotificationAccess();
            }
        }

        public async Task AskForNotificationAccess()
        {

            Console.WriteLine("notificaitons do not have access");
        }

        #endregion
    }
}
  1. 确保对命名空间有程序集引用
[assembly: Xamarin.Forms.Dependency(typeof(Foo.Bar.Droid.SomeFileName.CompanionAssociationRequest))]

  1. 现在将 OnActivityResult 放在 MainActivity 中。它似乎在其他任何地方都不起作用。我不知道如何使用 WiFi 配对,所以如果您有任何想法,请告诉我。

注意:我不会 JAVA,所以希望这是一个很好的近似值。

    protected override void OnActivityResult(int requestCode,Result resultCode,Intent data)
        {
            base.OnActivityResult(requestCode,resultCode,data);
            try
            {
                if (resultCode != Result.Ok)
                {
                    return;
                }
                if (requestCode == CompanionAssociationRequest.SELECT_DEVICE_REQUEST_CODE && data != null)
                {
                    #region Bluetooth                    
                    BluetoothDevice deviceToPair = (BluetoothDevice)data.GetParcelableExtra(CompanionDeviceManager.ExtraDevice);
                    #endregion
                    #region BluetoothLE                    
                    //Android.Bluetooth.LE.ScanResult deviceToPair = (Android.Bluetooth.LE.ScanResult)data.GetParcelableExtra(CompanionDeviceManager.ExtraDevice);
                    #endregion
                    #region Wifi                    
                    //Android.Net.Wifi.ScanResult deviceToPair = (Android.Net.Wifi.ScanResult)data.GetParcelableExtra(CompanionDeviceManager.ExtraDevice);
                    #endregion
                    if (deviceToPair != null)
                    {
                        #region Bluetooth
                        deviceToPair.CreateBond();
                        #endregion
                        #region BluetoothLE                        
                        //deviceToPair.Device.CreateBond();                        
                        #endregion
                        #region Wifi
                        //???
                        //Have been trying a few things but could not figure it out. 
                        #endregion
                        //do more stuff
                    }
                }
                else
                {
                    base.OnActivityResult(requestCode,data);
                }
            }
            catch (Exception ex)
            {                
                Console.WriteLine(ex.Message);
            }
        }}

我还没有真正尝试过 BluetoothLE,但我认为它应该可以工作。希望这可以帮助有人把头撞在桌子上,如果有人有任何改进,我将不胜感激。

Java 配对链接:Android companion device pairing

Microsoft 文档链接:Microsoft's documentation

这些确实是我能找到的仅有的一些文档,我偶然发现了一些其他方法来让系统运行。这几乎是 Java Pairing 示例的精确翻译,但我仍然花了很长时间来弄清楚如何格式化并弄清楚它应该如何协同工作。我还没有研究过滤器,希望它们会更容易设置。