1

是否可以在 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(); 包装器.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)
                    };
    

    ...

如果在上面的步骤 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}
4

2 回答 2

1

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

于 2015-05-24T17:07:57.553 回答
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 。帖子说不能从 JS 调用使用 XAML 的运行时组件。

Band SDK 要求调用从 UI 线程到达有 4 种情况。

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

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

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

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

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

这是对我有用的一段代码。该代码在 C# UI 线程(从电话应用程序)调用组件时有效,并且在非 UI 线程调用时也有效,因为解析调度程序的神奇代码行在 C# 进程中成功:

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

那行代码应该为 UI 线程解析调度程序。因此,我的实验代码获取了调度程序并安排了一个调用,该调用将与 UI 线程上的 Band 对话。“承诺”通过兼容的 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();
    }

问候, 安德鲁

于 2016-03-04T02:25:34.537 回答