How do I track my user’s steps while app is minimised?

Hello! I would like to track my user’s steps to give game rewards. However, all attempts to use the InputSystem.StepCounter have failed and the step counter output always reads zero. I think this is because the app never gets permission to use the device.

Any ideas how to make a pedometer work?

2 Answers

2

I’ve worked out the answer.

  1. Install Unity’s new Input System from the Package Manager.
  2. Install this free addon.
  3. In Project Settings click on Player/Publishing Settings and then enable ‘Custom Main Manifest’
  4. Navigate to the manifest itself at Assets\Plugins\Android\AndroidManifest.xml and add this line: <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> to the top of the MAnifest section:
  5. Create a monobehaviour called ‘StepLogger’ or similar (Don’t call it counter) and add the following code:
   [SerializeField]TextMeshProUGUI counterTMP, DEBUGTEXT;

   long stepOffset;
   void Start()
   {
       if (Application.isEditor) { return; }
       RequestPermission(); InputSystem.EnableDevice(StepCounter.current);
   }

   void Update()
   {
       if (Application.isEditor) { return; }

       if (stepOffset == 0)
       {
           stepOffset = StepCounter.current.stepCounter.ReadValue();
       }
       counterTMP.text = "Steps: " + (StepCounter.current.stepCounter.ReadValue() - stepOffset).ToString();
   }


   async void RequestPermission()
   {
       #if UNITY_EDITOR
           DEBUGTEXT.text = ("Editor Platform");
       #endif
       #if UNITY_ANDROID
           AndroidRuntimePermissions.Permission result = await AndroidRuntimePermissions.RequestPermissionAsync("android.permission.ACTIVITY_RECOGNITION");
           if (result == AndroidRuntimePermissions.Permission.Granted)
               DEBUGTEXT.text = ("Permissions seem to be granted.");
           else
            DEBUGTEXT.text = ("Permission state: " + result);
       #endif
   }
  1. In the editor: Drag your new monobehaviour onto a gameobject, if it isn’t already there, and create two TextMeshPro fields in your canvas. Attach one to the step counter and one to the Debug field (you can delete the second field once it’s working)
  2. Build for Android, and test it on your phone.

Omg your code works really well and thanks a lot for share it, it really helped me a lot! there is only 1 problem that i found, on first install i need to kill the app and restart it again or it will not work sadly… you know what could be doing that? @TiggyFairy

EDIT: This worked for us

using System;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;

public class StepLogger : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI DEBUGTEXT, counterTMP;
    public int simulatedSteps;
    public const float stepsPerKilometer = 1350.0f;
    long stepOffset;
    bool permissionGranted = false;

    void Start()
    {
        if (Application.isEditor)
        {
            DEBUGTEXT.text = "Running in Editor";
            return;
        }

        RequestPermission();
    }

    void Update()
    {
        if (Application.isEditor || !permissionGranted)
        {
            return;
        }

        if (StepCounter.current == null)
        {
            DEBUGTEXT.text = "StepCounter not available";
            return;
        }

        if (stepOffset == 0)
        {
            stepOffset = StepCounter.current.stepCounter.ReadValue();
            DEBUGTEXT.text = "Step offset " + stepOffset;
        }
        else
        {
            long currentSteps = StepCounter.current.stepCounter.ReadValue();
            long stepsTaken = currentSteps - stepOffset;
            counterTMP.text = "Steps: " + stepsTaken;

            try
            {
                Challenge.staticData.player.steps = (int)stepsTaken;
            }
            catch (OverflowException)
            {
                DEBUGTEXT.text = "Failure to convert long steps";
            }
        }
    }

    async void RequestPermission()
    {
#if UNITY_EDITOR
        DEBUGTEXT.text = "Editor Platform";
#endif
#if UNITY_ANDROID
        AndroidRuntimePermissions.Permission result = await AndroidRuntimePermissions.RequestPermissionAsync("android.permission.ACTIVITY_RECOGNITION");
        if (result == AndroidRuntimePermissions.Permission.Granted)
        {
            permissionGranted = true;
            DEBUGTEXT.text = "Permission granted";
            InitializeStepCounter();
        }
        else
        {
            DEBUGTEXT.text = "Permission state: " + result;
        }
#endif
    }

    void InitializeStepCounter()
    {
        InputSystem.EnableDevice(StepCounter.current);
        stepOffset = StepCounter.current.stepCounter.ReadValue();
    }

    void OnApplicationPause(bool pause)
    {
        if (!pause && permissionGranted)
        {
            // Reinitialize the step counter when the app is resumed
            InitializeStepCounter();
        }
    }
  }

I honestly have no idea, sorry. I don't really have that problem with it. Just a minor issue where it won't count steps for a little while, then updates to count them all at once.