如何在 Xamarin Forms 中获取 Samsung Health 步数

How to Get Samsung Health Step Count in Xamarin Forms

我正在尝试使用 Xamarin Forms(针对 Android 应用程序)从 Samsung Health 获取步数。

我尝试使用来自 Samsung Health SDK 的 SamsungHealthForXamarin to recreate the SimpleHealth 示例项目。

Java 示例项目在相同范围内使用匿名内联 类,这是我们在 C# 中无法做到的。所以看起来你必须构建一个 IConnectionListener 接口。

有没有人有使用 Xamarin Forms (C#) 从 Samsung Health 获取 "step data" 的经验? 我很想看到一个超级简单的例子,它只是在 C# 中获取今天的步数。好像不应该这么难。

如果我对您的理解正确,那么您的问题主要在于如何让连接侦听器知道其数据存储到底是什么。从 Java 上的所有侦听器只是 C# 中的 class 实现所需接口这一事实开始,我们可以像这样创建我们的侦听器:

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

重要的是第三行——内部属性Store。在这里,我们将保留对 HealthDataStore 的引用,这将取决于我们的侦听器。

我们的服务将如下所示:

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

同样,重要的一行是该方法的第三行 - 我们正在将商店分配给侦听器的 属性,以便我们可以在那里引用它。

同样的方法也适用于 StepCountReporter class:

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 个额外的 classes - StepResultHolderResultListener & StepObserver

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

之后,您可以按照您希望的任何方式通知 UI - 使用 Xamarin 的 MessagingCenter、使用事件、使用其他类型的观察者逻辑 - 取决于项目的架构。

关于该主题的一些旁注:

  1. 请注意,项目已移至 Bitbucket,如 README.md
  2. 中所述
  3. 与往常一样,您应该考虑一些限制。 Samsung Health docs - Restrictions

Samsung Health Android SDK runs on devices with Android 6.0 Marshmallow (API level 23) or above.

It requires Samsung Health installation. The latest SDK works with Samsung Health 6.2 or above. See the SDK and Samsung Health’s compatible versions here.

An app’s targetSdkVersion that uses Samsung Health Android SDK should be 26 or above.

Samsung Health is available on all Samsung smartphones and also non-Samsung Android smartphones with Marshmallow or above.