npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sahil_sensei/react-native-app-usage

v0.3.0

Published

Android App Usage Stats, Screen Time & Digital Wellbeing data for React Native

Readme

@sahil_sensei/react-native-app-usage

Android app usage, screen time, launch count, installed app metadata, and app icons for React Native.

Use this package when you want to build dashboards like Digital Wellbeing, screen time charts, app usage lists, focus mode summaries, or parental-control style usage views.

Breaking change in 0.3.0AppInfo.icon now returns a file:// URI pointing at a cached PNG on disk (was: data:image/png;base64,...). The native module writes the PNG to the host app's cacheDir/app-icons/ and only re-encodes when the app's versionCode or icon bytes change. New fields iconHash, versionCode, and versionName are also returned. Consumers using <Image source={{ uri: app.icon }} /> need no code change; consumers that previously decoded the base64 themselves should drop that step.

Features

  • Check whether Usage Access permission is enabled.
  • Open the Android Usage Access settings screen.
  • Get installed apps with app name, package name, UID, cached PNG icon URI, icon hash, version code, and version name.
  • Get daily, weekly, and monthly app usage stats.
  • Get hourly usage breakdown for one app on a selected date.
  • TypeScript types included.

Platform Support

| Platform | Support | | --- | --- | | Android | Supported | | iOS | Not supported |

Android is required because the package uses Android's UsageStats APIs.

Installation

npm install @sahil_sensei/react-native-app-usage

or:

yarn add @sahil_sensei/react-native-app-usage

For React Native CLI projects, rebuild the Android app after installing:

npx react-native run-android

Android Permission

The package includes these Android permissions in its manifest:

<uses-permission
  android:name="android.permission.PACKAGE_USAGE_STATS"
  tools:ignore="ProtectedPermissions" />

<uses-permission
  android:name="android.permission.QUERY_ALL_PACKAGES"
  tools:ignore="QueryAllPackagesPermission" />

PACKAGE_USAGE_STATS is a special Android permission. Users must enable it manually in system settings; it cannot be requested with a normal runtime permission dialog.

Use hasUsagePermission() to check access and openUsagePermissionSettings() to send the user to the correct Android settings page.

Quick Start

import {
  getDailyUsage,
  hasUsagePermission,
  openUsagePermissionSettings,
} from '@sahil_sensei/react-native-app-usage';

async function loadUsage() {
  const hasPermission = await hasUsagePermission();

  if (!hasPermission) {
    await openUsagePermissionSettings();
    return [];
  }

  const usage = await getDailyUsage();

  return usage.sort(
    (a, b) => b.totalTimeInForeground - a.totalTimeInForeground
  );
}

Complete React Native Example

This example renders today's app usage with app icons and formatted screen time.

import React, { useEffect, useState } from 'react';
import {
  ActivityIndicator,
  FlatList,
  Image,
  SafeAreaView,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import {
  getDailyUsage,
  hasUsagePermission,
  openUsagePermissionSettings,
} from '@sahil_sensei/react-native-app-usage';
import type { AppUsageStat } from '@sahil_sensei/react-native-app-usage';

function formatDuration(ms: number) {
  const totalMinutes = Math.floor(ms / 60000);
  const hours = Math.floor(totalMinutes / 60);
  const minutes = totalMinutes % 60;

  if (hours === 0) {
    return `${minutes}m`;
  }

  return `${hours}h ${minutes}m`;
}

export default function AppUsageScreen() {
  const [loading, setLoading] = useState(true);
  const [hasPermission, setHasPermission] = useState(false);
  const [apps, setApps] = useState<AppUsageStat[]>([]);

  async function load() {
    setLoading(true);

    try {
      const permission = await hasUsagePermission();
      setHasPermission(permission);

      if (!permission) {
        setApps([]);
        return;
      }

      const usage = await getDailyUsage();
      const sortedUsage = usage.sort(
        (a, b) => b.totalTimeInForeground - a.totalTimeInForeground
      );

      setApps(sortedUsage);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    load();
  }, []);

  if (loading) {
    return <ActivityIndicator />;
  }

  if (!hasPermission) {
    return (
      <SafeAreaView style={{ flex: 1, padding: 24, justifyContent: 'center' }}>
        <Text style={{ fontSize: 20, fontWeight: '700', marginBottom: 8 }}>
          Usage access required
        </Text>
        <Text style={{ marginBottom: 16 }}>
          Enable Usage Access so the app can read screen time data.
        </Text>
        <TouchableOpacity onPress={openUsagePermissionSettings}>
          <Text style={{ color: '#2563eb', fontWeight: '700' }}>
            Open Settings
          </Text>
        </TouchableOpacity>
      </SafeAreaView>
    );
  }

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <FlatList
        data={apps}
        keyExtractor={(item) => item.packageName}
        contentContainerStyle={{ padding: 16 }}
        renderItem={({ item }) => (
          <View
            style={{
              flexDirection: 'row',
              alignItems: 'center',
              paddingVertical: 12,
              borderBottomWidth: 1,
              borderBottomColor: '#e5e7eb',
            }}
          >
            <Image
              source={{ uri: item.icon }}
              style={{ width: 44, height: 44, borderRadius: 10, marginRight: 12 }}
            />
            <View style={{ flex: 1 }}>
              <Text style={{ fontSize: 16, fontWeight: '700' }}>
                {item.name}
              </Text>
              <Text style={{ color: '#6b7280' }}>{item.packageName}</Text>
            </View>
            <Text style={{ fontWeight: '700' }}>
              {formatDuration(item.totalTimeInForeground)}
            </Text>
          </View>
        )}
      />
    </SafeAreaView>
  );
}

API

hasUsagePermission()

Checks whether the app has Android Usage Access permission.

const hasPermission: boolean = await hasUsagePermission();

openUsagePermissionSettings()

Opens the Android Usage Access settings screen.

await openUsagePermissionSettings();

getInstalledApps(includeSystemApps?)

Returns installed apps with metadata and icons.

const apps = await getInstalledApps();
const allApps = await getInstalledApps(true);

getDailyUsage()

Returns app usage for the last day.

const usage = await getDailyUsage();

getWeeklyUsage()

Returns app usage for the last week.

const usage = await getWeeklyUsage();

getMonthlyUsage()

Returns app usage for the last month.

const usage = await getMonthlyUsage();

getHourlyUsage(packageName, date?)

Returns a 24-hour breakdown for one app. If date is not provided, today's date is used.

const hourly = await getHourlyUsage('com.instagram.android');
const yesterday = await getHourlyUsage(
  'com.instagram.android',
  new Date('2026-05-05')
);

Types

interface AppInfo {
  packageName: string;
  name: string;
  uid: string;
  icon: string;
}

interface AppUsageStat extends AppInfo {
  totalTimeInForeground: number;
  lastTimeUsed: number;
  launchCount: number;
}

interface HourlyUsage {
  hour: number;
  durationMs: number;
  opens: number;
}

Example Response

[
  {
    packageName: 'com.instagram.android',
    name: 'Instagram',
    uid: '10245',
    icon: 'data:image/png;base64,iVBORw0KGgo...',
    totalTimeInForeground: 5400000,
    lastTimeUsed: 1778063400000,
    launchCount: 12,
  },
];

totalTimeInForeground and durationMs are returned in milliseconds. lastTimeUsed is a Unix timestamp in milliseconds.

Notes

  • This package is Android only.
  • Always check permission before calling usage APIs.
  • App icons are returned as base64 data URIs and can be used directly with <Image source={{ uri: icon }} />.
  • If you publish your app on Google Play, review Google's policy for QUERY_ALL_PACKAGES before release.

License

MIT


Made with create-react-native-library