I'm trying to use native api. I have the following code to get the 5 most used apps. It's a Native Android module with TypeScript because I can't call APIs with React Native:
fun getUsageData(startTime: Double, endTime: Double, successCallback: Callback) {
val usageStatsManager = reactApplicationContext.getSystemService(Context.USAGE_STATS_SERVICE) as
// Query usage stats
val usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime.toLong(), endTime.toLong())
// Sort usage stats by total time in foreground
usageStatsList.sortByDescending { it.totalTimeInForeground }
// Extract package names of top 5 used apps
val topApps: WritableArray = WritableNativeArray()
for (i in 0 until minOf(5, usageStatsList.size)) {
val packageName = usageStatsList[i].packageName
topApps.pushString(packageName)
}
// // Pass the top apps list back to React Native
successCallback.invoke(topApps)
}
But my list is always empty in Typescript and I don't know why:
LOG Top 5 used apps: []
And this is my TypeScript code:
const getUsageData = () => {
const startTime = new Date().getTime() - (7 * 24 * 60 * 60 * 1000);
const endTime = new Date().getTime();
UsageStatsModule.getUsageData(Number(startTime), Number(endTime), (topApps : any) => {
console.log('Top 5 used apps:', topApps);
});
};
I don't know how to start for debug, because I have no error and I didn't practice mobile development.
Edit :
I made a few changes to get more information but it wasn't conclusive:
In the manifest.xml :
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
and in the module file :
@ReactMethod
fun getUsageData(startTime: Double, endTime: Double, successCallback: Callback) {
try {
val usageStatsManager: UsageStatsManager = this.reactApplicationContext.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val cal: Calendar = Calendar.getInstance()
cal.add(Calendar.DAY_OF_MONTH, -1)
// Query usage stats
val usageStatsList = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, cal.timeInMillis, System.currentTimeMillis())
?: throw SecurityException("Permission denied or usage stats not available")
// Sort usage stats by total time in foreground
usageStatsList.sortByDescending { it.totalTimeInForeground }
Log.d("a", "a : " + usageStatsList.size)
// Extract package names of top 5 used apps
val topApps: WritableArray = WritableNativeArray()
for(i in 0..usageStatsList.size - 1) {
val packageName = usageStatsList[i].packageName
topApps.pushString(packageName)
}
// Pass the top apps list back to React Native
successCallback.invoke(topApps)
} catch (e: Exception) {
// Handle exceptions
e.printStackTrace()
// Notify React Native about the error
// You might want to handle this differently based on your app's requirements
successCallback.invoke(WritableNativeArray().apply {
pushString("Error: ${e.message}")
})
}
}
Edit :
PLease, anyone have an idee ? I m still stuck on this !
I had the same issue. Declaring the permission in the manifest isn't enough in this case (view the guidelines https://developer.android.com/training/permissions/requesting-special). The user needs to grant permission through the Settings app, which you launch with your activity context:
Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS, Uri.fromParts("package", packageName, null)).also {
ContextCompat.startActivity(context, it, null)
}