アンドロイド - UsageStatsManagerでアプリ履歴を取得する

By JS | Last updated: August 09, 2019

UsageStatsManagerはアプリ履歴を提供するサービスです。 ここで提供されるAPIを使用すると、最近実行されたアプリが何なのか、アプリの使用時間は、それぞれどのくらいあるかを知ることができます。

UsageStatsManagerはアプリの記録をQueryできるAPIを提供し、DAY、MONTH、YEARの時間単位(Interval)で区切られた結果を得ることができます。 結果は UsageStatsオブジェクトで返されています。このオブジェクトは、アプリの名前、最後の使用時刻、アプリが実行されたすべての時間などの情報が含まれています。

UsageStatsManagerは UsageStatsのほかUsageEvents、ConfigurationStatsを提供します。 返されるコンテンツが違うだけで照会する方法は似ています。ここでは、 UsageStatsを照会する方法に焦点を合わせて説明します。

UsageStatsManagerは、他のアプリの情報を得たときにandroid.permission.PACKAGE _USAGE_STATS権限を要求します。 この権限は、システムエプマン得ることができます。通常のアプリがこの権限を取得するには、ユーザーに設定に入って権限を付与してくれと要請してください。

許可を要求する方法をまず説明し、アプリの使用履歴を照会する方法について紹介します。

この記事で使用するコードは、すべての鼻間違って作成しました。

アクセス許可要求

自分のアプリのAndroidManifest.xmlに以下のように権限を追加する必要があります。通常のアプリは自動的に権限が付与されません。

<uses-permission
    android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions" />

そして、アプリが実行されると、ユーザーが自分のアプリに PACKAGE_USAGE_STATS権限を付与してくれたのかをチェックする必要があります。

以下のコードでユーザーが権限を付与してくれたのかチェックすることができます。 AppOpsManagerは権限が支払わはパーミッションに対してユーザーが強制的に権限を付与してくれるサービスです。 そのため、 AppOpsManager APIを介してアクセス権を強制的に与えられていることを確認することです。

private fun checkForPermission(): Boolean {
    val appOps = getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    val mode = appOps.checkOpNoThrow(OPSTR_GET_USAGE_STATS, Process.myUid(), packageName)
    return mode == MODE_ALLOWED
}

もし権限がない場合に設定できるアクティビティを実行してくれます。アクションがSettings.ACTION_USAGE_ACCESS_SETTINGSなインテントを実行すると、設定画面を浮かせます。

if (!checkForPermission()) {
    Log.i(TAG, "The user may not allow the access to apps usage. ")
    Toast.makeText(
        this,
        "Failed to retrieve app usage statistics. " +
                "You may need to enable access for this app through " +
                "Settings > Security > Apps with usage access",
        Toast.LENGTH_LONG
    ).show()
    startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
} else {
    // We have the permission. Query app usage stats.
}

セッティングインテントをstartすると、次のような画面が表示されます。 show usage stats permission settings

自分のアプリを選択すると、次のように権限を付与することができる画面が表示されます。 Permit usage accessを押し権限を付与します。 permit usage access

今のアプリは、権限を持つようになりました。権限チェック関数を再実行してみると、trueを返してくれます。

アプリ履歴Query方法

UsageStatsManagerを介してアプリ履歴を取得する 次のQuery APIを利用します。たとえば、引数としてINTERVAL_YEARLYが渡された場合、1年単位で囲んでアプリの履歴を整理して、結果として返されています。 そしてクエリするデータの開始時刻と終了時刻を引数として渡します。 コメントのように、引数がそう渡される、エプドゥルの使用記録は、2013〜2015の間、1年単位で測定され、結果として返されます。

/*
* intervalType = INTERVAL_YEARLY
* beginTime = 2013
* endTime = 2015 (exclusive)
*
* Results:
* 2013 - com.example.alpha
* 2013 - com.example.beta
* 2014 - com.example.alpha
* 2014 - com.example.beta
*
* @param intervalType The time interval by which the stats are aggregated.
* @param beginTime The inclusive beginning of the range of stats to include in the results.
* @param endTime The exclusive end of the range of stats to include in the results.
* @return A list of {@link UsageStats}
*/
public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime)

Interval typeは、次のようなものがあります。

Interval type
INTERVAL_BEST 指定された期間に最も適したタイプでクエリ
INTERVAL_DAILY 1日の時間単位でのクエリ
INTERVAL_MONTHLY 1ヶ月の時間単位でのクエリ
INTERVAL_WEEKLY 1週間の時間単位でのクエリ
INTERVAL_YEARLY 1年の時間単位でのクエリ

したがって、上記のAPIとタイプを利用して、次のように実装することができます。

private fun getAppUsageStats(): MutableList<UsageStats> {
    val cal = Calendar.getInstance()
    cal.add(Calendar.YEAR, -1)    // 1

    val usageStatsManager =
        getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager // 2
    val queryUsageStats = usageStatsManager.queryUsageStats(
            UsageStatsManager.INTERVAL_DAILY, cal.timeInMillis, System.currentTimeMillis() // 3
        )
    return queryUsageStats
}

'// 1'ような番号に順番を付け、以下説明しました。

  1. 現在のから1年前の時間を取得します。 1年間のデータのみをクエリするためです。
  2. UsageStatsManagerオブジェクトを取得します。
  3. 引数と一緒にクエリをします。インターバルはDAILYに設定し、時間因子はmillisに渡す必要があります。

ちなみに、currentTimeMillis()はLongを返して、現実の世界の現在の時刻を意味します。 "1970年1月1日"を基準にLongの値を返します。

以下は、リターンされた List<UsageStats>オブジェクトを出力するコードです。 まず、私は最後に使用されたアプリを先に示すので、最後に使用時間にsortingをしました。 そしてforEachですべてのデータを出力しました。時間はDateオブジェクトを使用して、読みやすくしました。

private fun showAppUsageStats(usageStats: MutableList<UsageStats>) {
    usageStats.sortWith(Comparator { right, left ->
        compareValues(left.lastTimeUsed, right.lastTimeUsed)
    })

    usageStats.forEach { it ->
        Log.d(TAG, "packageName: ${it.packageName}, lastTimeUsed: ${Date(it.lastTimeUsed)}, " +
                "totalTimeInForeground: ${it.totalTimeInForeground}")
    }
}

次に、このように、ログが出力されます。アプリが最後に使用された時間はいつなのか、総実行時間はどのくらいなのか、出力しました。

2019-08-11 14:28:49.330 com.codechacha.myapplication D/MainActivity: packageName: com.codechacha.myapplication, lastTimeUsed: Sun Aug 11 14:28:35 GMT+09:00 2019, totalTimeInForeground: 7619163
2019-08-11 14:28:49.330 com.codechacha.myapplication D/MainActivity: packageName: com.google.android.apps.nexuslauncher, lastTimeUsed: Sun Aug 11 14:28:35 GMT+09:00 2019, totalTimeInForeground: 6512061
2019-08-11 14:28:49.331 com.codechacha.myapplication D/MainActivity: packageName: com.android.settings, lastTimeUsed: Sun Aug 11 14:28:13 GMT+09:00 2019, totalTimeInForeground: 2105253
2019-08-11 14:28:49.331 com.codechacha.myapplication D/MainActivity: packageName: com.google.android.packageinstaller, lastTimeUsed: Sun Aug 11 13:58:16 GMT+09:00 2019, totalTimeInForeground: 25370240
....

UsageStatsのデータは以下のAPIを利用して取得することができます。

API Returned Data
getPackageName アプリ名
getLastTimeUsed 最後に使用された時間
getTotalTimeInForeground Foregroundで実行されたフルタイム
getAppLaunchCount 実行された回数

まとめ

UsageStatsManagerについて調べ見て、アプリ履歴を取得するためにクエリを実行する方法と結果を出力する方法を説明しました。

この記事で作成したサンプルコードは、GitHubで確認することができます。

Google sampleも参考になれば良いです。

参考

Related Posts

codechachaCopyright ©2019 codechacha