한국어 사용자는 Korean version.를 참조하십시오.
This library provides an interface for tracking the number of steps taken by the user in a React Native app. This package uses the StepCounter (or custom accelerometer-based step-counter) sensor API on Android and the Core Motion framework on iOS to count steps. It is built as a TurboModule and, from v0.3.0, requires React Native New Architecture (TurboModule/Fabric).
# if you use pure npm (what a classic!),
npm install @dongminyu/react-native-step-counter# or if you prefer to use Yarn (I love it's parallel install feature),
yarn add @dongminyu/react-native-step-counter# or if you use pnpm (it's fast and efficient),
pnpm add @dongminyu/react-native-step-counterNative modules will automatically connect after React Native 0.60 version. So you don't need to link the native modules manually.
⚠️ New Architecture required from v0.3.0: This version requires React Native's New Architecture (TurboModule/Fabric) to be enabled.✅ Minimum supported React Native version:
>=0.71.0Expo Go, Expo managed workflow, and React Native versions below
0.71.0are not supported.
👣 If you have not yet enabled the New Architecture, follow the guide below. If it is already enabled, you can skip to the next step.
IF YOU WANT SEE A DEMO IN STANDALONE REACT-NATIVE APPLICATION, SEE WALKING_TRACKER EXAMPLE REPO
Thank you for your interest in my first NPM open source package! I've received a lot of issue reports on various issues, especially the react-native's NEW ARCHITECTURE backwards compatibility, and I've more or less finalized those issues by fixing the code structure across the board. We had generated an example folder from create-react-native-library's template and used it for this project, but due to the structure of that template, we found that the example folder contained a lot of code that was not suitable for reference in a working app, as it was part of the overall development process rather than a standalone application. For this reason, I'm going to independently manage the example application, which we had been developing informally as a sub-repository, as a repository named walking_tracker. I'd really appreciate it if you could take this into consideration.
-
Applying a new architecture to React Native applications (Common)
- React Native released the support for the New Architecture with the release
0.68.0. - This is written with the expectation that you’re using the latest React Native release.
- You can find instructions on how to upgrade in the page upgrading to new versions.
- write all JS bridges with TypeScript (or Flow.js) because Codegen requires explicitly defined types. As you know, JavaScript is a dynamically typed language, so it is not possible to generate code.
- use hermes and flipper debugging tools.
- React Native released the support for the New Architecture with the release
-
Applying a new architecture to React Native iOS applications
1. set platform version to 12.4 or higher.
- platform :ios, '11.0' + platform :ios, '12.4' # ↓ or you can use the variable of (react_native_pods.rb) + platform :ios, min_ios_version_supported
2. set NODE_BINARY to .xcode.env file.
echo 'export NODE_BINARY=$(command -v node)' > .xcode.env
3. Fix an API Change in the
AppDelegate.mfile.- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif }4. Rename all Objective-C(.m) files to Objective-C++ (.mm) 5. Make your AppDelegate conform to RCTAppDelegate
-
AppDelegate.hexample:- #import <React/RCTBridgeDelegate.h> + #import <RCTAppDelegate.h> #import <UIKit/UIKit.h> - @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate> + @interface AppDelegate : RCTAppDelegate - @property (nonatomic, strong) UIWindow *window; @end
-
AppDelegate.mmexample:#import "AppDelegate.h" #import <React/RCTBundleURLProvider.h> @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.moduleName = @"StepCounterExample"; self.initialProps = @{}; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } - (BOOL)concurrentRootEnabled { return true; } @end
Note for Swift projects (React Native 0.76+): If your app uses a Swift-based
AppDelegate.swift, New Architecture is already enabled by default. No AppDelegate changes are required — simply runpod installwithRCT_NEW_ARCH_ENABLED=1.-
Run
pod installexport RCT_NEW_ARCH_ENABLED=1 cd ios && pod install
-
-
Applying a new architecture to React Native Android applications
- If your project has React Native later than
v0.71.0, you already meet all the prerequisites to use the New Architecture on Android. - You will only need to set
newArchEnabledtotruein yourandroid/gradle.propertiesfile.
- If your project has React Native later than
If you prefer to read the official documentation, you can find it here.
3 uses-permission, 3 uses-feature
<!-- android/src/main/AndroidManifest.xml-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stepcounter">
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.BODY_SENSORS_BACKGROUND" />
<uses-feature
android:name="android.hardware.sensor.stepcounter"
android:required="false" />
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="true" />
</manifest>set NSMotionUsageDescription
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
...
<key>NSMotionUsageDescription</key>
<string>We want to access your motion data to count your steps.</string>
...
</plist>-
isStepCountingSupported(): Promise<Record<string, boolean>>: method to check if the device has a feature related step counter or accelerometer.- One key for the response object is
granted, whether the app user has granted this feature permission, andsupportedis whether the device supports this feature. - This NativeModule can apply algorithms to a raw accelerometer to extract walking event data without activity sensor privileges, regardless of this response, but it is not recommended. You must write a code that stops tracking sensor events if user denies read-permission - even if you can do that.
- One key for the response object is
-
startStepCounterUpdate(start: Date, callBack: StepCountUpdateCallback):EventSubscription:- If the pedometer sensor is available and supported on the device, register it with the listener in the sensor manager, and return the step count event listener.
- If the pedometer sensor is not supported by the device or is not available, register the accelerometer sensor with the listener, generate an accel event through a vector algorithm filter and receive it to the app.
-
stopStepCounterUpdate(): void:- Removes the subscription registered by
startStepCounterUpdateand stops the native sensor session.
- Removes the subscription registered by
-
StepCountData:-
Common Interface
steps: This is a number property that indicates the number of steps taken by the user during the specified time period.startDate: This is a number property that indicates the start date of the data in Unix timestamp format, measured in milliseconds.endDate: This is a number property that indicates the end date of the data in Unix timestamp format, measured in milliseconds.distance: This is a number property that indicates the distance in meters that the user has walked or run during the specified time period.counterType: The name of the sensor used to count the number of steps. In iOS, only theCMPedometeris returned, and in Android, theStepCounterorAccelerometeris returned depending on the device state.
-
iOS Only
floorsAscended: This is a number property that indicates the number of floors the user has ascended during the specified time period. It can be nil if the device does not support this feature.floorsDescended: This is a number property that indicates the number of floors the user has descended during the specified time period. It can be nil if the device does not support this feature.
-
To use the Step Counter Library in your React Native app, follow these steps:
Import the library into your React Native app.
import React, { useEffect, useState } from "react";
import {
isStepCountingSupported,
parseStepData,
startStepCounterUpdate,
stopStepCounterUpdate,
} from "@dongminyu/react-native-step-counter";Use the isStepCountingSupported method to check if the device has a step counter or accelerometer sensor.
const [supported, setSupported] = useState(false);
const [granted, setGranted] = useState(false);
async function askPermission() {
isStepCountingSupported().then((result) => {
console.debug("🚀 - isStepCountingSupported", result);
setGranted(result.granted === true);
setSupported(result.supported === true);
});
}Call the startStepCounterUpdate method to start the step counter service.
const [steps, setSteps] = useState(0);
async function startStepCounter() {
startStepCounterUpdate(new Date(), (data) => {
console.debug(parseStepData(data));
setSteps(data.steps);
});
}Here's an example of a complete React component that uses the NativeStepCounter.
Link to Example Application: here
See the Release Notes for a list of changes.
See the Contributing Guide to learn how to contribute to the repository and the development workflow.
MIT
Made with create-react-native-library