You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native如何获取其他应用屏幕时长?有无可用库或包?

在React Native中获取其他应用屏幕时长的方案

一、Android权限前提

Android 10(API 29)及以上版本,获取其他应用的使用统计数据必须申请PACKAGE_USAGE_STATS权限。这个权限无法通过常规权限弹窗请求,必须引导用户跳转到系统设置的「有权查看使用情况的应用」页面手动开启。

二、可用的npm包尝试

1. react-native-app-usage

这个库支持获取应用使用时长,适配Android和iOS(但iOS受系统限制只能获取自身应用数据)。使用步骤:

  • 先在android/app/src/main/AndroidManifest.xml中添加权限:
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
    
  • RN端代码示例:
    import AppUsage from 'react-native-app-usage';
    
    // 检查并引导开启权限
    const checkAndRequestPermission = async () => {
      const hasPermission = await AppUsage.checkPermission();
      if (!hasPermission) {
        AppUsage.openSettings(); // 跳转到系统权限设置页
      }
    };
    
    // 获取过去24小时的应用使用数据
    const fetchUsageData = async () => {
      const startDate = new Date();
      startDate.setDate(startDate.getDate() - 1);
      try {
        const usageData = await AppUsage.fetchUsage(startDate, new Date());
        console.log(usageData); // 返回包含包名、使用时长等字段的数组
      } catch (err) {
        console.error('获取数据失败:', err);
      }
    };
    
    注意:部分最新RN版本可能存在兼容性问题,建议先在测试项目中验证。

2. react-native-usage-stats

专门针对Android UsageStatsManager API封装的库,用法更贴近原生API:

  • 同样需要先在AndroidManifest.xml中添加上述权限。
  • RN端代码示例:
    import UsageStats from 'react-native-usage-stats';
    
    const getAppUsage = async () => {
      const isGranted = await UsageStats.checkPermission();
      if (!isGranted) {
        await UsageStats.requestPermission(); // 自动跳转到设置页
      }
      // 按天获取使用统计
      const stats = await UsageStats.queryUsageStats('DAILY');
      console.log(stats);
    };
    

三、自定义原生模块(当现有库不兼容时)

如果上述npm包无法满足需求,作为Android新手,可以快速实现一个简单的原生模块:

  1. 在Android项目中创建UsageStatsModule.java类:
    import android.app.usage.UsageStats;
    import android.app.usage.UsageStatsManager;
    import android.content.Context;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.bridge.ReactContextBaseJavaModule;
    import com.facebook.react.bridge.ReactMethod;
    import com.facebook.react.bridge.Promise;
    import com.facebook.react.bridge.WritableArray;
    import com.facebook.react.bridge.WritableMap;
    import com.facebook.react.bridge.WritableNativeArray;
    import com.facebook.react.bridge.WritableNativeMap;
    import java.util.List;
    import java.util.Calendar;
    
    public class UsageStatsModule extends ReactContextBaseJavaModule {
        private UsageStatsManager usageStatsManager;
    
        public UsageStatsModule(ReactApplicationContext reactContext) {
            super(reactContext);
            usageStatsManager = (UsageStatsManager) reactContext.getSystemService(Context.USAGE_STATS_SERVICE);
        }
    
        @Override
        public String getName() {
            return "UsageStatsModule";
        }
    
        @ReactMethod
        public void getDailyAppUsage(Promise promise) {
            Calendar calendar = Calendar.getInstance();
            long endTime = calendar.getTimeInMillis();
            calendar.add(Calendar.DAY_OF_YEAR, -1);
            long startTime = calendar.getTimeInMillis();
    
            List<UsageStats> statsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
            WritableArray result = new WritableNativeArray();
    
            for (UsageStats stats : statsList) {
                WritableMap map = new WritableNativeMap();
                map.putString("packageName", stats.getPackageName());
                map.putDouble("totalTimeInForeground", stats.getTotalTimeInForeground() / 1000); // 转成秒
                result.pushMap(map);
            }
            promise.resolve(result);
        }
    }
    
  2. 在MainApplication.java中注册模块:
    import com.yourpackage.UsageStatsModule; // 替换成你的包名
    import com.facebook.react.ReactPackage;
    import com.facebook.react.shell.MainReactPackage;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Collections;
    
    public class MainApplication extends Application implements ReactApplication {
        // ... 其他代码
        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.asList(
                new MainReactPackage(),
                new UsageStatsPackage() // 注册自定义模块
            );
        }
    
        // 添加自定义Package类
        private class UsageStatsPackage implements ReactPackage {
            @Override
            public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
                return Arrays.asList(new UsageStatsModule(reactContext));
            }
    
            @Override
            public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
                return Collections.emptyList();
            }
        }
    }
    
  3. RN端调用:
    import { NativeModules } from 'react-native';
    const { UsageStatsModule } = NativeModules;
    
    const fetchNativeUsage = async () => {
      try {
        const stats = await UsageStatsModule.getDailyAppUsage();
        console.log(stats);
      } catch (err) {
        console.error(err);
      }
    };
    

四、核心注意事项

  • 权限必须由用户手动开启,代码无法自动授予。
  • 数据返回的是应用包名,若需要显示应用名称,可以通过Android的PackageManager获取(原生模块中实现或用额外的RN库)。
  • 不同Android版本的UsageStatsManager行为略有差异,建议在多个版本的设备上测试。

内容的提问来源于stack exchange,提问作者nitesh saini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:15:00