accurate_step_counter 1.7.0 copy "accurate_step_counter: ^1.7.0" to clipboard
accurate_step_counter: ^1.7.0 copied to clipboard

A highly accurate step counter plugin using accelerometer-based detection with low-pass filtering and peak detection. Includes Hive database logging with warmup validation. Supports foreground, backgr [...]

Accurate Step Counter #

pub package License: MIT

A simple, accurate step counter for Flutter. Works in foreground, background, and terminated states. Health Connect-like API with persistent storage.

✨ Features #

  • 🎯 Accurate - Uses Android's hardware step detector
  • 💾 Persistent - Steps saved to local DB (Hive)
  • 📱 All States - Foreground, background, AND terminated
  • 🚀 Simple API - One-line setup, no complexity
  • 🔋 Battery Efficient - Event-driven, not polling
  • ⏱️ Inactivity Timeout - Auto-reset sessions after idle periods
  • 🌍 External Import - Import steps from Google Fit, Apple Health, etc.

📱 Platform Support #

Platform Status
Android ✅ Full support (API 19+)
iOS ❌ Not supported

🚀 Quick Start #

1. Install #

dependencies:
  accurate_step_counter: ^1.7.0

2. Add Permissions #

In android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

3. Use It! #

import 'package:accurate_step_counter/accurate_step_counter.dart';

final stepCounter = AccurateStepCounter();

// 🚀 One-line setup!
await stepCounter.initSteps();

// Get today's steps
final todaySteps = await stepCounter.getTodayStepCount();

// Watch real-time updates
stepCounter.watchTodaySteps().listen((steps) {
  print('Steps today: $steps');
});

// Get yesterday's steps
final yesterdaySteps = await stepCounter.getYesterdayStepCount();

// Custom date range
final weekSteps = await stepCounter.getStepCount(
  start: DateTime.now().subtract(Duration(days: 7)),
  end: DateTime.now(),
);

📖 Complete Example #

import 'package:flutter/material.dart';
import 'package:accurate_step_counter/accurate_step_counter.dart';
import 'package:permission_handler/permission_handler.dart';

class StepCounterPage extends StatefulWidget {
  @override
  State<StepCounterPage> createState() => _StepCounterPageState();
}

class _StepCounterPageState extends State<StepCounterPage> 
    with WidgetsBindingObserver {
  final _stepCounter = AccurateStepCounter();
  int _steps = 0;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _init();
  }

  Future<void> _init() async {
    // Request permissions
    await Permission.activityRecognition.request();
    
    // Initialize step counter
    await _stepCounter.initSteps();
    
    // Watch today's steps (emits immediately with stored value!)
    _stepCounter.watchTodaySteps().listen((steps) {
      setState(() => _steps = steps);
    });
    
    // Handle terminated state sync
    _stepCounter.onTerminatedStepsDetected = (steps, from, to) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Synced $steps missed steps!')),
      );
    };
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    _stepCounter.setAppState(state); // Important for source tracking!
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _stepCounter.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('$_steps steps', style: TextStyle(fontSize: 48)),
      ),
    );
  }
}

🔧 API Reference #

Core Methods #

Method Description
initSteps() One-line setup (DB + detector + logging)
getTodayStepCount() Get today's total steps
getYesterdayStepCount() Get yesterday's total steps
getStepCount(start, end) Get steps for date range
watchTodaySteps() Real-time stream of today's steps
setAppState(state) Track foreground/background (call in didChangeAppLifecycleState)
dispose() Clean up resources

Reading Logs #

// Get all step logs with details
final logs = await stepCounter.getStepLogs();

for (final log in logs) {
  print('${log.stepCount} steps');
  print('From: ${log.fromTime} To: ${log.toTime}');
  print('Source: ${log.source}'); // foreground, background, terminated, external
}

// Filter by date or source
final todayLogs = await stepCounter.getStepLogs(from: startOfToday);
final bgLogs = await stepCounter.getStepLogs(source: StepRecordSource.background);
final externalLogs = await stepCounter.getStepLogs(source: StepRecordSource.external);

// Get stats
final stats = await stepCounter.getStepStats();
// {totalSteps, foregroundSteps, backgroundSteps, terminatedSteps, ...}

Importing External Steps (NEW in v1.6.0) #

// Import steps from Google Fit, Apple Health, wearables, etc.
await stepCounter.writeStepsToAggregated(
  stepCount: 500,
  fromTime: DateTime.now().subtract(Duration(hours: 2)),
  toTime: DateTime.now(),
  source: StepRecordSource.external, // Mark as external import
);
// All listeners automatically notified!

// Query external steps
final externalSteps = await stepCounter.getStepsBySource(
  StepRecordSource.external,
);

Data Management #

// Clear all logs
await stepCounter.clearStepLogs();

// Delete old logs
await stepCounter.deleteStepLogsBefore(
  DateTime.now().subtract(Duration(days: 30)),
);

📱 How It Works (Hybrid Architecture v1.7.0) #

App State Android ≤10 (API ≤29) Android 11+ (API 30+)
🟢 Foreground Native detector (realtime) Native detector (realtime)
🟡 Background Native detector (realtime) Native detector (realtime)
🔴 Terminated Foreground service with notification TYPE_STEP_COUNTER sync on restart

Key Benefits of v1.7.0:

  • Better UX: No persistent notification when app is running
  • Better battery: Foreground service only runs when needed (terminated state)
  • Realtime updates: Native detector for instant step feedback in all running states
  • No duplicates: Separate sync paths prevent double-counting

⚙️ Advanced Configuration #

For more control, use the advanced setup:

// Initialize database
await stepCounter.initializeLogging(debugLogging: true);

// Start with custom config
await stepCounter.start(
  config: StepDetectorConfig(
    enableOsLevelSync: true,
    useForegroundServiceOnOldDevices: true,
    foregroundServiceMaxApiLevel: 29, // Use service on Android ≤10
  ),
);

// Start logging with preset
await stepCounter.startLogging(config: StepRecordConfig.walking());
// Presets: walking(), running(), sensitive(), conservative(), aggregated()

// Custom config with inactivity timeout (NEW in v1.6.0)
await stepCounter.startLogging(
  config: StepRecordConfig.walking().copyWith(
    inactivityTimeoutMs: 10000, // Reset after 10s of no steps
  ),
);

📄 License #

MIT License - see LICENSE

1
likes
0
points
1.44k
downloads

Publisher

verified publisherrahulsha.com.np

Weekly Downloads

A highly accurate step counter plugin using accelerometer-based detection with low-pass filtering and peak detection. Includes Hive database logging with warmup validation. Supports foreground, background, and terminated state tracking.

Repository (GitHub)
View/report issues

Documentation

Documentation

License

unknown (license)

Dependencies

flutter, hive, hive_flutter

More

Packages that depend on accurate_step_counter

Packages that implement accurate_step_counter