如何在React Native Android中获取其他应用的使用信息
在React Native Android中获取其他应用使用时长的实现方案
1. 权限配置
首先需要在Android项目的AndroidManifest.xml中添加系统保护权限:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
注意:该权限无法通过React Native的PermissionsAndroid请求弹窗获取,必须引导用户手动进入系统设置的**「有权查看使用情况的应用」**页面开启权限。
2. 编写Android原生模块
React Native没有内置获取其他应用使用时长的API,需要自定义原生模块调用Android的UsageStatsManager:
步骤2.1 创建原生模块类
在android/app/src/main/java/com/[你的项目包名]/下创建AppUsageModule.java:
package com.yourprojectname; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.Promise; import android.app.AppOpsManager; import android.content.Context; import android.os.Process; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import java.util.HashMap; import java.util.List; import java.util.Map; public class AppUsageModule extends ReactContextBaseJavaModule { public AppUsageModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { // 模块名称,React Native端将通过这个名称调用 return "AppUsageModule"; } // 检查是否拥有使用情况统计权限 private boolean hasUsageStatsPermission() { AppOpsManager appOps = (AppOpsManager) getReactApplicationContext().getSystemService(Context.APP_OPS_SERVICE); int mode = appOps.checkOpNoThrow( AppOpsManager.OPSTR_GET_USAGE_STATS, Process.myUid(), getReactApplicationContext().getPackageName() ); return mode == AppOpsManager.MODE_ALLOWED; } @ReactMethod public void getAppUsageToday(ReadableArray packageNames, Promise promise) { // 先检查权限 if (!hasUsageStatsPermission()) { promise.reject("PERMISSION_DENIED", "需要开启使用情况访问权限"); return; } UsageStatsManager usageStatsManager = (UsageStatsManager) getReactApplicationContext() .getSystemService(Context.USAGE_STATS_SERVICE); long endTime = System.currentTimeMillis(); long startTime = endTime - 24 * 60 * 60 * 1000; // 今日0点到当前时间的时间范围 // 查询今日的应用使用统计数据 List<UsageStats> usageStatsList = usageStatsManager.queryUsageStats( UsageStatsManager.INTERVAL_DAILY, startTime, endTime ); Map<String, Double> resultMap = new HashMap<>(); // 遍历目标包名,计算每个应用的总前台时长 for (int i = 0; i < packageNames.size(); i++) { String packageName = packageNames.getString(i); long totalForegroundTime = 0; for (UsageStats stats : usageStatsList) { if (stats.getPackageName().equals(packageName)) { totalForegroundTime += stats.getTotalTimeInForeground(); } } // 转换为小时(保留两位小数),也可以根据需求转为分钟 double hours = totalForegroundTime / (1000.0 * 60 * 60); resultMap.put(packageName, hours); } promise.resolve(resultMap); } }
步骤2.2 注册原生模块
创建AppUsagePackage.java来注册模块:
package com.yourprojectname; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class AppUsagePackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new AppUsageModule(reactContext)); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
步骤2.3 在MainApplication中添加包
修改MainApplication.java的getPackages方法,添加自定义包:
@Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); // 添加自定义模块包 packages.add(new AppUsagePackage()); return packages; }
3. React Native端调用
在React Native组件中调用原生模块,并处理权限和结果:
import { NativeModules, Alert, Linking, Platform } from 'react-native'; // 导入自定义原生模块 const AppUsageModule = NativeModules.AppUsageModule; // 获取指定应用今日使用时长的方法 const getAppUsageData = async () => { // 仅在Android平台执行 if (Platform.OS !== 'android') return; try { // 传入目标应用的包名列表 const usageData = await AppUsageModule.getAppUsageToday([ 'com.whatsapp', // WhatsApp 'com.instagram.android',// Instagram 'com.google.android.gm' // Gmail(示例邮箱应用) ]); // 格式化数据为易读格式 const formattedData = Object.entries(usageData).map(([packageName, hours]) => { let durationText; if (hours >= 1) { durationText = `${hours.toFixed(1)}小时`; } else { const minutes = Math.round(hours * 60); durationText = `${minutes}分钟`; } return { appName: getAppDisplayName(packageName), duration: durationText }; }); // 输出或展示结果 console.log('应用使用时长:', formattedData); // 这里可以将formattedData渲染到UI上 } catch (error) { // 处理权限缺失的情况 if (error.code === 'PERMISSION_DENIED') { Alert.alert( '权限提示', '需要开启「有权查看使用情况的应用」权限才能获取应用使用时长', [ { text: '取消', style: 'cancel' }, { text: '去设置', onPress: () => Linking.openSettings() } ] ); } else { console.error('获取应用使用时长失败:', error); } } }; // 根据包名映射应用名称 const getAppDisplayName = (packageName) => { switch(packageName) { case 'com.whatsapp': return 'WhatsApp'; case 'com.instagram.android': return 'Instagram'; case 'com.google.android.gm': return 'Gmail'; default: return packageName; } }; // 调用方法示例 // getAppUsageData();
4. 关键注意事项
- Android版本限制:
UsageStatsManager仅支持Android 5.0(API 21)及以上版本,低于该版本无法实现此功能。 - 权限特殊性:必须引导用户手动开启权限,无法通过常规权限请求流程自动获取。
- 包名准确性:目标应用的包名必须准确,不同应用的包名可能不同(例如国内邮箱应用需自行查找对应包名)。
- 数据精度:返回的时长是应用在前台的累计时间,与系统设置中显示的统计数据可能存在细微差异,取决于系统的统计逻辑。
内容的提问来源于stack exchange,提问作者Sayali Sonawane
相关产品推荐
相关产品推荐

