web-dev-qa-db-ja.com

XamarinフォームでSamsung Healthの歩数を取得する方法

Xamarinフォームを使用して、Samsung Healthから歩数を取得しようとしています(Androidアプリの場合)。

SamsungHealthForXamarin を使用して、Samsung Health SDKから SimpleHealth サンプルプロジェクトを再作成してみました。

Javaサンプルプロジェクトでは、C#では実行できない同じスコープ内で匿名のインラインクラスを使用しています。そのため、代わりにIConnectionListenerインターフェイスを構築する必要があります。

Xamarinフォーム(C#)を使用してSamsung Healthから「ステップデータ」を取得した経験はありますか?今日の歩数をC#で取得するという非常に単純な例を見たいです。それほど難しいことではないようです。

4
Brad Bamford

私があなたを正しく理解している場合、問題は主に、接続リスナーにそのデータストアが正確に何であるかを知らせる方法にあります。 Javaのすべてのリスナーは、必要なインターフェイスを実装するC#の単なるクラスであるという事実から始めて、次のようにリスナーを作成できます。

public class ConnectionListener : HealthDataStore.IConnectionListener
{
    internal HealthDataStore Store { get; set; }

    public void OnConnected()
    {
        var stepCountReporter = new StepCountReporter(Store);
        // NOTE: Check for permissions here
        stepCountReporter.Start();
    }
    public void OnConnectionFailed(HealthConnectionErrorResult p0)
    {
        // Health data service is not available.
    }
    public void OnDisconnected()
    {
        Store.DisconnectService();
    }
}

重要な行は3番目の行、つまり内部プロパティStoreです。ここでは、リスナーに依存するHealthDataStoreへの参照を保持します。

サービスは次のようになります。

private void InitStepService()
{
    var connectionListener = new ConnectionListener();
    store = new HealthDataStore(this, connectionListener);
    connectionListener.Store = store; // This is the important line
    store.ConnectService();
}

繰り返しますが、重要な行はメソッドの3行目です。ストアをリスナーのプロパティに割り当てて、そこに参照を持たせることができます。

同じアプローチがStepCountReporterクラスにも適用されます。

public class StepCountReporter
{
    private readonly HealthDataStore store;
    private const long OneDayInMillis = 24 * 60 * 60 * 1000L;

    public StepCountReporter(HealthDataStore store)
    {
        this.store = store;
    }

    public void Start()
    {
        HealthDataObserver.AddObserver(store, HealthConstants.StepCount.HealthDataType,
            new StepObserver(ReadTodayStepCount));
        ReadTodayStepCount();
    }

    private void ReadTodayStepCount()
    {
        var resolver = new HealthDataResolver(store, null);

        // Set time range from start time of today to the current time
        var startTime = DateTime.Now.Date.Ticks;
        var endTime = startTime + OneDayInMillis;

        ReadRequestBuilder requestBuilder = new ReadRequestBuilder()
            .SetDataType(HealthConstants.StepCount.HealthDataType)
            .SetProperties(new[] { HealthConstants.StepCount.Count })
            .SetLocalTimeRange(HealthConstants.StepCount.StartTime, HealthConstants.StepCount.TimeOffset,
                startTime, endTime);

        IReadRequest request = requestBuilder.Build();

        try
        {
            resolver.Read(request).SetResultListener(new StepResultHolderResultListener());
        }
        catch (Exception)
        {
            // Getting step count fails.
        }
    }
}

ここに2つの追加クラスが必要になります-StepResultHolderResultListenerStepObserver

StepResultHolderResultListener

public class StepResultHolderResultListener : IHealthResultHolderResultListener
{
    public void OnResult(Java.Lang.Object resultObject)
    {
        if (resultObject is ReadResult result)
        {
            int count = 0;

            try
            {
                var iterator = result.Iterator();
                while (iterator.HasNext)
                {
                    var data = (HealthData) iterator.Next();
                    count += data.GetInt(HealthConstants.StepCount.Count);
                }
            }
            finally
            {
                result.Close();
            }

            // Update your UI here with the count variable
        }
    }

    // Rest of the methods from the interface
}

StepObserver

public class StepObserver : HealthDataObserver
{
    private readonly Action readTodayStepCountAction;

    private StepObserver(Handler p0)
        : base(p0)
    {
    }

    public StepObserver(Action readTodayStepCountAction)
        : this((Handler) null)
    {
        this.readTodayStepCountAction = readTodayStepCountAction;
    }

    public override void OnChange(string dataTypeName)
    {
        readTodayStepCountAction();
    }
}

その後、プロジェクトのアーキテクチャに応じて、Xamarinの MessagingCenter を使用して、イベントを使用して、他の種類のオブザーバーロジックを使用して、任意の方法でUIに通知できます。

トピックに関するいくつかの補足事項:

  1. README.mdに記載されているように、プロジェクトは Bitbucket に移動されています。
  2. いつものように、考慮すべきいくつかの制限があります。 Samsung Health docs-制限事項

Samsung Health Android SDKはAndroid 6.0 Marshmallow(APIレベル23)以上のデバイスで動作します。

Samsung Healthのインストールが必要です。最新のSDKはSamsung Health 6.2以降で動作します。 SDKとSamsung Healthの互換バージョンについては、こちらをご覧ください。

Samsung Healthを使用するアプリのtargetSdkVersion Android SDKは26以上である必要があります。

Samsung Healthは、すべてのSamsungスマートフォンと、Samsung以外のAndroid Marshmallow以上のスマートフォン)で利用できます。

2
Mihail Duchev