Microsoft Band SDK与Windows运行时组件

时间:2015-05-21 15:03:08

标签: microsoft-band

是否可以在Windows运行时组件中使用Microsoft Band SDK? GetBandsAsync可以使用,但在使用以下连接时失败:

IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0])

我正在使用Microsoft Band SDK 1.3.10518。我已将rfcomm功能添加到应用程序包清单中,并且出现以下异常:

System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime.InteropServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Runtime.InteropServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at Microsoft.Band.MarshalUtils.GetBytes[T](T& structure, Byte[] resultArray, Int32 offset)
   at Microsoft.Band.BandClient.CheckFirmwareSdkBit(FirmwareSdkCheckPlatform platform, Byte reserved)
   at Microsoft.Band.BandClientManager.<ConnectAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at BandController.Band.<StartRemoteControlAsync>d__5.MoveNext()} System.Exception {System.IO.FileNotFoundException}

要重现错误,我就是这样做的:

  1. 在Visual Studio中创建一个新的空白应用程序(Windows Phone Silverlight)
  2. 向应用添加按钮(假设为“测试乐队”)并为Tap事件添加处理程序
  3. 将Windows运行时组件(Windows Phone)添加到解决方案中,将其命名为BandTest,命名空间BandWrapper
  4. 将Microsoft Band SDK添加到BandWrapper项目
  5. 在Silverlight项目的Package.appxmanifext中添加rfcomm和邻近功能(对于BandWrapper rfcomm由Microsoft Band SDK安装程序添加)
  6. 按如下方式实施测试按钮处理程序:

    private void Button_Tap(object sender,System.Windows.Input.GestureEventArgs e)         {             BandWrapper.BandTest wrapper = new BandWrapper.BandTest();             wrapper.TestBand();         }

  7. 在SDK中的运行时组件副本中,使用public async void TestBand()方法进行以下示例:

            try
            {
                // Get the list of Microsoft Bands paired to the phone/tablet/PC.
                IBandInfo[] pairedBands = await BandClientManager.Instance.GetBandsAsync();
                if (pairedBands.Length < 1)
                {
                    //this.viewModel.StatusMessage = "This sample app requires a Microsoft Band paired to your device. Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.";
                    return;
                }
    
                // Connect to Microsoft Band.
                using (IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
                {
                    // We'll create a Tile that looks like this:
                    // +--------------------+
                    // | MY CARD            | 
                    // | |||||||||||||||||  | 
                    // | 123456789          |
                    // +--------------------+
    
                    // First, we'll prepare the layout for the Tile page described above.
                    TextBlock myCardTextBlock = new TextBlock()
                    {
                        Color = Colors.Blue.ToBandColor(),
                        ElementId = 1, // the Id of the TextBlock element; we'll use it later to set its text to "MY CARD"
                        Rect = new PageRect(0, 0, 200, 25)
                    };
    

    ...

  8. 如果在上面的步骤1中,我创建了一个Windows Phone应用程序(而不是Silverlight),测试方法的执行达到

    await bandClient.TileManager.AddTileAsync(myTile);
    

    然后失败了:

    System.TypeLoadException: Could not find Windows Runtime type 'Windows.Foundation'.
       at System.StubHelpers.WinRTTypeNameConverter.GetTypeFromWinRTTypeName(String typeName, Boolean& isPrimitive)
       at System.StubHelpers.SystemTypeMarshaler.ConvertToManaged(TypeNameNative* pNativeType, Type& managedType)
       at Windows.UI.Xaml.Controls.Frame.Navigate(Type sourcePageType, Object parameter)
       at Microsoft.Band.StoreApplicationPlatformProvider`2.<>c__DisplayClassd`1.<GetConsentAsync>b__a()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
       at Microsoft.Band.StoreApplicationPlatformProvider`2.<GetConsentAsync>d__f`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
       at Microsoft.Band.BandClient.<>c__DisplayClass6f.<<AddTileAsync>b__6c>d__71.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at BandWrapper.BandTest.<TestBand>d__5.MoveNext()}   System.Exception {System.TypeLoadException}
    

2 个答案:

答案 0 :(得分:1)

是的,有可能! 您必须确保,当您在Windows运行时组件中测试连接时(来自后台任务),您之前没有从正在运行的主应用程序连接Band。即使从Using-Statement中打开连接并且应该释放所有资源,仍然有一些端口正在使用Band。在这种情况下,从Windows运行时组件连接Band将失败。

答案 1 :(得分:0)

早些时候Band SDK中存在漏洞,这完全阻止了这种情况。使用当前版本的SDK,我成功创建了一个能够创建磁贴并部署布局的Windows运行时组件。不幸的是,我只是成功地从C#调用它并且未能找到提供JavaScript支持的方法。

看起来目前的情况是不可能的。请看这篇文章:https://social.msdn.microsoft.com/Forums/en-US/93d04495-171f-411d-bd2c-82f55888827b/windows-runtime-ui-component?forum=winappswithcsharp。帖子说使用XAML的运行时组件不能从JS调用。

当SDK要求来自UI线程的呼叫时,Band SDK有4种情况。

  1. 在第一次托管SDK的应用程序调用蓝牙库时,该应用程序会与操作系统通话以请求用户的权限。如果该调用不在UI线程上,则蓝牙库将抛出异常。一旦用户同意,就可以从非UI线程调用蓝牙。

  2. UI线程必须至少有一次调用才能请求同意获取用户心率以订阅心率数据。订阅本身可以在任何线程上完成。请求同意的UI是SDK的一部分。

  3. AddTile始终询问用户的权限。 UI对话框是SDK的一部分。从非UI线程调用AddTile将失败。

  4. 添加磁贴时,代码必须提供其图标。 SDK的当前实现为诸如WritableBitmap之类的XAML类提供ToBandIcon扩展方法。如果调用到达非UI线程,则位图的构造将失败并返回RPC_WRONG_THREAD。

  5. 在我看来,Windows运行时组件的需求是通过对JavaScript,C#和C ++的支持来证明的。如果您不需要JavaScript,那么您的项目可能会成功。

    以下是适用于我的代码。当C#UI线程(来自电话应用程序)调用组件时代码工作,并且当非UI线程调用时它也可以工作,因为解析调度程序的神奇代码行在C#进程中成功:

    var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;

    该行代码应该解析UI线程的调度程序。所以我的实验代码获得了调度程序并安排了一个调用,该调用将与UI线程上的Band通信。 &#34;承诺&#34;使用兼容的IAsyncAction返回给调用者。如果整个想法奏效,JavaScript会很好地处理它。

        private bool inCall;
    
        public IAsyncAction TestBandAsync()
        {
            var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
    
            var completionSource = new TaskCompletionSource<int>();
    
            // x is to suppress CS2014
            var x = dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
            {
                try
                {
                    if (this.inCall)
                        throw new InvalidOperationException("Currently in call!");
    
                    this.inCall = true;
                    try
                    {
                        WriteableBitmap textBitmap = new WriteableBitmap(1, 1);
    
                        // Get the list of Microsoft Bands paired to the phone.
                        IBandInfo[] pairedBands = await BandClientManager.Instance.GetBandsAsync();
                        if (pairedBands.Length < 1)
                            throw new InvalidOperationException("No bands found!");
    
                        var bitmap = await LoadBitmapAsync("ms-appx:///Assets/Smile.png");
                        var bandIcon = bitmap.ToBandIcon();
    
                        // Connect to Microsoft Band.
                        using (IBandClient bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
                        {
                            // Create a Tile with a TextButton on it.
                            Guid myTileId = new Guid("12408A60-13EB-46C2-9D24-F14BF6A033C6");
    
                            BandTile myTile = new BandTile(myTileId)
                            {
                                Name = "My Tile",
                                TileIcon = bandIcon,
                                SmallIcon = bandIcon
                            };
    
                            var designed = new BandTileLayout1();
                            myTile.PageLayouts.Add(designed.Layout);
    
                            // Remove the Tile from the Band, if present. An application won't need to do this everytime it runs. 
                            // But in case you modify this sample code and run it again, let's make sure to start fresh.
                            await bandClient.TileManager.RemoveTileAsync(myTileId);
    
                            await designed.LoadIconsAsync(myTile);
    
                            // Create the Tile on the Band.
                            await bandClient.TileManager.AddTileAsync(myTile);
                            await bandClient.TileManager.SetPagesAsync
                                (myTileId,
                                new PageData(new Guid("5F5FD06E-BD37-4B71-B36C-3ED9D721F200"),
                                0,
                                designed.Data.All));
                        }
                    }
                    finally
                    {
                        this.inCall = false;
                    }
    
                    completionSource.SetResult(0);
                }
                catch (Exception ex)
                {
                    completionSource.SetException(ex);
                }
            });
    
            return completionSource.Task.AsAsyncAction();
        }
    

    此致 安德鲁