본문 바로가기

Android

[Android] 다른 앱 사용기록 조회

개요

사용자가 모바일에서 다른 어떤 앱을 얼마나 자주 사용하는지 모니터하는 서비스

여기서 제공하는 API를 사용하면,

  1. 최근 실행된 앱이 무엇인지, 사용시간은 각각 얼마인지 알 수 있음 (UsageStatsManager)
  2. 기간별 앱들의 네트워크 사용량을 알 수 있음 (NetwordStatsManager)
  3. 앱들의 저장공간을 알 수 있음 (StorageStatsManager)

권한

다른 앱들의 사용기록 정보를 얻기 위한 권한 PACKAGE_USAGE_STATS 필요함 (직접 요청 O)

<?xml version="1.0" encoding="utf-8"?>
<manifest>
        <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
        tools:ignore="ProtectedPermissions" />
</manifest>

1. UsageStatsManager

  • 앱 사용기록을 Query 할 수 있는 API를 제공
  • 조회하고자 하는 기간을 설정 (ex. 2020.04.01 - 2021.04.01)
  • 시간 단위(Interval) 설정 (ex. days, weeks, months, years로 구분된 결과 받을 수 있음)
// 1년 전부터 현재까지 사용한 모든 앱들의 사용기록을 한달 단위로 조회
private fun getAppUsageStats(): MutableList<UsageStats> = run {
    val calendar = Calendar.getInstance()
    calendar.add(Calendar.YEAR, -1)                        // 날짜설정(1년 전으로)

    val usageStatsManager = requireContext().getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager

      // 사용기록 조회
    usageStatsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_MONTHLY,        // 한달 단위로
        calendar.timeInMillis,                                // 1년 전부터
        System.currentTimeMillis()                        // 현재까지
    )
}
  • Query 결과로는 전체 앱들의 사용기록 List<UsageStats> 반환
  • UsageStats 에는 패키지 이름, 마지막 사용 시간, 전체 실행 시간 등의 정보를 얻을 수 있음
UsageStats  
getPackageName 패키지 이름
getLastTimeUsed 마지막 사용 시간
getTotalTimeInForeground 전체 실행 시간

특이사항

  • 반환된 앱의 패키지 이름(ex. com.lee.oneweekonebook)을 앱의 이름(ex. 일주일책)으로 변환하여 사용자에게 보여줘야 함
  • 삭제한 앱의 사용내역도 가져옴
  • 조회결과 겹치는 days, weeks, months, years가 있으므로 한번 더 grouping 필요함

시간단위(Interval)에 따른 결과의 개수

시간단위 설명
INTERVAL_DAILY 앱 사용했던 날 중 최근 몇 개만(최대 10개) 가져옴
INTERVAL_WEEKLY 최근 4주의 데이터만 가져옴
NTERVAL_MONTHLY 최근 6달의 데이터만 가져옴
INTERVAL_YEARLY 연도별로 가져옴

2. NetworkStatsManager

  • 앱 네트워크 사용기록을 Query 할 수 있는 API를 제공
  • 조회하고자 하는 기간을 설정 (ex. 2020.04.01 - 2021.04.01)
  • 네트워크 상태(와이파이와 모바일 데이터)에 따른 사용 결과를 받을 수 있음
  • 전체 또는 특정 앱(uid) 조회
private fun getNetworkUsageStats(uid: Int) {
    val calendar = Calendar.getInstance()
    calendar.add(Calendar.YEAR, -1)                        // 날짜설정(1년 전으로)

    val networkStatsManager = requireContext().getSystemService(Context.NETWORK_STATS_SERVICE) as NetworkStatsManager

      // 해당 앱(uid)에 대한 네트워크 기록 조회
    val networkWifiStats: NetworkStats = networkStatsManager.queryDetailsForUid(
        NetworkCapabilities.TRANSPORT_WIFI,        // Wifi에 사용된 데이터 조회(모바일 데이터 조회 시 - TRANSPORT_CELLULAR)
        null,
        calendar.timeInMillis,                                // 1년 전부터
        System.currentTimeMillis(),                        // 현재까지
        uid
    )
}
  • Query 결과인 NetworkStatsNetworkStats.Bucket() 을 통해 조회
var totalWifiNetwork = 0L
val bucketWifi = NetworkStats.Bucket()
while (networkWifiStats.hasNextBucket()) {
    networkWifiStats.getNextBucket(bucketWifi)
    totalWifiNetwork += bucketWifi.rxBytes + bucketWifi.txBytes
}
  • NetworkStats.Bucket() 에는 주고 받은 bytes의 개수, 마지막 사용 시간 등의 정보를 얻을 수 있음
NetworkStats.Bucket()  
getRxBytes 받은 bytes의 개수 (TCP와 UDP 사용량 포함)
getTxBytes 보낸 bytes의 개수 (TCP와 UDP 사용량 포함)
getEndTimeStamp 마지막 사용 시간

특이사항

  • 와이파이와 모바일 데이터 네트워크 사용량 따로 조회해야함
  • 네트워크 사용량 조회 시 전체 혹은 특정 앱(uid)을 조회할 수 있음
  • 전체를 조회하면 각 앱에 대한 uid와 함께 네트워크 사용량이 반환되는데, 사용자에게 보여줄 시 packageManager 를 통해 uid를 앱 이름으로 변환해야함

3. StorageStatsManager

  • 앱 저장공간을 Query 할 수 있는 API를 제공
  • 전체 또는 특정 앱(packageName 이나 uid) 조회
private fun getStorageUsageStats(packageName: String) {
    val storageStatsManager = requireContext().getSystemService(Context.STORAGE_STATS_SERVICE) as StorageStatsManager
    val storageManager =  requireContext().getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
    storageVolumes.map {
        val uuid = it.uuid?.let { uuid ->
            UUID.fromString(uuid)
        } ?: StorageManager.UUID_DEFAULT
        try {
            // 패키지 이름으로 저장공간 조회
            val result = storageStatsManager.queryStatsForPackage(uuid, packageName, android.os.Process.myUserHandle())
                result.appBytes
              result.dataBytes
              result.cacheBytes
        } catch (e: Exception) {
            Logger.d(e.message)
        }
    }
}
  • Query 결과인 StorageStats 앱의 크기, 데이터 사용공간, 캐시 사용공간 등의 정보를 얻을 수 있음
StorageStats  
getAppBytes 앱의 크기 / APK files, optimized compiler output, and unpacked native libraries
getDataBytes 데이터 사용공간 / getDataDir(), getCacheDir(), getCodeCacheDir()
getCacheBytes 캐시 사용공간 / getCacheDir() and getCodeCacheDir()

특이사항

  • sdkVersion 26 이상부터 StorageStatsManager 사용 가능
  • 사용공간 중 데이터만의 크기를 알기 위해서는 데이터 사용공간 에서 캐시의 사용공간을 빼줘야함

참고

API 공식 문서