Skip to content

Commit

Permalink
Feat: Add option to display app usage stats.
Browse files Browse the repository at this point in the history
Added functionality to display app usage statistics in the home screen. When enabled, the total screen time excluding the launcher itself is shown at the bottom of the home screen.

- Added a new preference to toggle the display of app usage statistics.
- Modified the UI to show the total screen time when app usage stats are enabled.
- Integrated usage stats retrieval and calculation methods.
- Updated layout XML to include a TextView for displaying total screen time.

This commit enhances the user experience by providing insight into screen usage patterns directly on the home screen.
  • Loading branch information
HeCodes2Much committed Apr 26, 2024
1 parent 3ac18e5 commit b2bc061
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
AppDrawerFlag.SetLongSwipeLeft -> prefs.appLongSwipeLeft = appModel
AppDrawerFlag.SetLongSwipeRight -> prefs.appLongSwipeRight = appModel
AppDrawerFlag.SetClickClock -> prefs.appClickClock = appModel
AppDrawerFlag.SetAppUsage -> prefs.appClickUsage = appModel
AppDrawerFlag.SetClickDate -> prefs.appClickDate = appModel
AppDrawerFlag.SetDoubleTap -> prefs.appDoubleTap = appModel
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ object Constants {
SetLongSwipeLeft,
SetLongSwipeRight,
SetClickClock,
SetAppUsage,
SetClickDate,
SetDoubleTap,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ private const val LONG_SWIPE_DOWN_ACTION = "LONG_SWIPE_DOWN_ACTION"
private const val LONG_SWIPE_RIGHT_ACTION = "LONG_SWIPE_RIGHT_ACTION"
private const val LONG_SWIPE_LEFT_ACTION = "LONG_SWIPE_LEFT_ACTION"
private const val CLICK_CLOCK_ACTION = "CLICK_CLOCK_ACTION"
private const val CLICK_APP_USAGE = "CLICK_APP_USAGE"
private const val CLICK_DATE_ACTION = "CLICK_DATE_ACTION"
private const val DOUBLE_TAP_ACTION = "DOUBLE_TAP_ACTION"
private const val HIDDEN_APPS = "HIDDEN_APPS"
Expand All @@ -55,6 +56,7 @@ private const val APP_PACKAGE = "APP_PACKAGE"
private const val APP_USER = "APP_USER"
private const val APP_ALIAS = "APP_ALIAS"
private const val APP_ACTIVITY = "APP_ACTIVITY"
private const val APP_USAGE_STATS = "APP_USAGE_STATS"
private const val APP_OPACITY = "APP_OPACITY"
private const val APP_THEME = "APP_THEME"

Expand All @@ -67,6 +69,7 @@ private const val LONG_SWIPE_DOWN = "LONG_SWIPE_DOWN"
private const val LONG_SWIPE_LEFT = "LONG_SWIPE_LEFT"
private const val LONG_SWIPE_RIGHT = "LONG_SWIPE_RIGHT"
private const val CLICK_CLOCK = "CLICK_CLOCK"
private const val CLICK_USAGE = "CLICK_USAGE"
private const val CLICK_DATE = "CLICK_DATE"
private const val DOUBLE_TAP = "DOUBLE_TAP"
private const val CUSTOM_FONT = "CUSTOM_FONT"
Expand Down Expand Up @@ -162,6 +165,10 @@ class Prefs(val context: Context) {
get() = prefs.getInt(APP_OPACITY, 128)
set(value) = prefs.edit().putInt(APP_OPACITY, value).apply()

var appUsageStats: Boolean
get() = prefs.getBoolean(APP_USAGE_STATS, false)
set(value) = prefs.edit().putBoolean(APP_USAGE_STATS, value).apply()

var homeAlignment: Gravity
get() {
val string = prefs.getString(
Expand Down Expand Up @@ -272,6 +279,10 @@ class Prefs(val context: Context) {
get() = loadAction(CLICK_CLOCK_ACTION, Constants.Action.OpenApp)
set(value) = storeAction(CLICK_CLOCK_ACTION, value)

var clickAppUsageAction: Constants.Action
get() = loadAction(CLICK_APP_USAGE, Constants.Action.OpenApp)
set(value) = storeAction(CLICK_APP_USAGE, value)

var clickDateAction: Constants.Action
get() = loadAction(CLICK_DATE_ACTION, Constants.Action.OpenApp)
set(value) = storeAction(CLICK_DATE_ACTION, value)
Expand Down Expand Up @@ -370,6 +381,10 @@ class Prefs(val context: Context) {
get() = loadApp(CLICK_CLOCK)
set(appModel) = storeApp(CLICK_CLOCK, appModel)

var appClickUsage: AppModel
get() = loadApp(CLICK_USAGE)
set(appModel) = storeApp(CLICK_USAGE, appModel)

var appClickDate: AppModel
get() = loadApp(CLICK_DATE)
set(appModel) = storeApp(CLICK_DATE, appModel)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.github.droidworksstudio.mlauncher.helper

import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.Build
import java.io.File
import java.io.FileInputStream
import java.security.MessageDigest
import java.util.Calendar

object AppDetailsHelper {

Expand All @@ -29,6 +31,72 @@ object AppDetailsHelper {
}
}

fun getUsageStats(context: Context, packageName: String): Long {
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
val startTime = calendar.timeInMillis
val endTime = System.currentTimeMillis()

val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as? UsageStatsManager
val usageStatsList = usageStatsManager?.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime)
var totalUsageTime: Long = 0

usageStatsList?.let { statsList ->
for (usageStats in statsList) {
if (usageStats.packageName == packageName) {
totalUsageTime = usageStats.totalTimeInForeground
}
}
}

return totalUsageTime
}

fun getTotalScreenTime(context: Context): Long {
val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
val startTime = calendar.timeInMillis
val endTime = System.currentTimeMillis()

var totalScreenTime: Long = 0

val packageName = context.packageName

val usageStatsList = usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY, startTime, endTime
)

for (usageStats in usageStatsList) {
if (usageStats.packageName != packageName) {
totalScreenTime += usageStats.totalTimeInForeground
}
}

return totalScreenTime
}


fun formatMillisToHMS(millis: Long): String {
val hours = millis / (1000 * 60 * 60)
val minutes = (millis % (1000 * 60 * 60)) / (1000 * 60)

val formattedString = StringBuilder()
if (hours > 0) {
formattedString.append("$hours h ")
}
if (minutes > 0 || hours > 0) {
formattedString.append("$minutes m ")
}
formattedString.append("")
return formattedString.toString().trim()
}


fun getAppVersionAndHash(context: Context, packageName: String, pm: PackageManager): AppDetails? {
val pkgInstalled = context.isPackageInstalled(packageName)
if (pkgInstalled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.R
import android.app.Activity
import android.app.AlertDialog
import android.app.AppOpsManager
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.DialogInterface
Expand Down Expand Up @@ -286,6 +287,23 @@ fun openAlarmApp(context: Context) {
}
}

fun openDigitalWellbeing(context: Context) {
val packageName = "com.google.android.apps.wellbeing"
val className = "com.google.android.apps.wellbeing.settings.TopLevelSettingsActivity"

val intent = Intent()
intent.component = ComponentName(packageName, className)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
// Digital Wellbeing app is not installed or cannot be opened
// Handle this case as needed
showToastLong(context,"Digital Wellbeing is not available on this device.")
}
}

fun openCalendar(context: Context) {
try {
val cal: Calendar = Calendar.getInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class AppDrawerFragment : Fragment() {
AppDrawerFlag.SetShortSwipeUp,
AppDrawerFlag.SetShortSwipeDown,
AppDrawerFlag.SetClickClock,
AppDrawerFlag.SetAppUsage,
AppDrawerFlag.SetClickDate -> {
binding.drawerButton.setOnClickListener {
findNavController().popBackStack()
Expand Down

0 comments on commit b2bc061

Please sign in to comment.