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(); 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)
                    };
    

    ...

上記の手順 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

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 から呼び出すことはできないと書かれています。

Band SDK には、UI スレッドからの呼び出しを要求する状況が 4 つあります。

  1. SDK をホストするアプリケーションが最初に Bluetooth ライブラリを呼び出しているとき、そのライブラリは OS と通信してユーザーにアクセス許可を要求します。その呼び出しが UI スレッド上にない場合、Bluetooth ライブラリは例外をスローします。ユーザーが同意すると、非 UI スレッドから Bluetooth を呼び出すことができます。

  2. 心拍数データをサブスクライブするには、ユーザーの心拍数を取得するための同意を要求するために、UI スレッドで少なくとも 1 つの呼び出しが必要です。サブスクリプション自体は、任意のスレッドで実行できます。同意を要求する UI は SDK の一部です。

  3. AddTile は常にユーザーに許可を求めます。UI ダイアログは SDK の一部です。非 UI スレッドから AddTile を呼び出すと失敗します。

  4. タイルを追加するとき、コードはそのアイコンを提供する必要があります。SDK の現在の実装では、WritableBitmap などの XAML クラスの ToBandIcon 拡張メソッドが提供されています。呼び出しが非 UI スレッドに到着した場合、ビットマップの構築は RPC_WRONG_THREAD で失敗します。

私の考えでは、Windows ランタイム コンポーネントの必要性は、JavaScript、C#、および C++ のサポートによって正当化されました。JavaScript が必要ない場合は、プロジェクトが成功する可能性があります。

これが私のために働いたコードです。このコードは、コンポーネントが C# UI スレッドによって (電話アプリケーションから) 呼び出されたときに機能し、非 UI スレッドによって呼び出されたときにも機能します。これは、ディスパッチャーを解決するコードの魔法の行が C# プロセスで成功するためです。

var ディスパッチャ = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;

そのコード行は、UI スレッドのディスパッチャーを解決するはずです。したがって、私の実験的なコードはディスパッチャを取得し、Band on UI スレッドと通信する呼び出しをスケジュールします。「約束」は、互換性のある 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 に答える