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端代码示例:
注意:部分最新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); } };
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新手,可以快速实现一个简单的原生模块:
- 在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); } } - 在
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(); } } } - 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
相关产品推荐
相关产品推荐

