前提
Windows 10
Android Studio最新版
Java
この方法は、2020/02/27時点では私のスマートフォンのおいては正常に動作しました。
仕様変更があるかもしれないので、コピペしてうまく行かない場合は公式ドキュメントを参考にしましょう。
やりたいこと
他のアプリがその日どれくらい起動していたかを取得する必要がありました。
例えば、下の画像はActionDashというアプリで、他のアプリの起動時間を表示しています。
結論から言うと、UsageStatsManagerを使えば良いです。
UsageStatsManager
権限関係
まず、下のようにAndroidManifest.xml
に記載してください。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="****">
<!-- 下の二行を追加 -->
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<application>
<!-- 省略 -->
</application>
</manifest>
次に、permission checkを行います。
普通のpermissionの方法ではなく、特別な方法を使用します。
private boolean checkReadStatsPermission() {
// AppOpsManagerを取得
AppOpsManager aom = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
// GET_USAGE_STATSのステータスを取得
int mode = aom.checkOp(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), getPackageName());
if (mode == AppOpsManager.MODE_DEFAULT) {
// AppOpsの状態がデフォルトなら通常のpermissionチェックを行う。
// 普通のアプリならfalse
return checkPermission("android.permission.PACKAGE_USAGE_STATS", android.os.Process.myPid(), android.os.Process.myUid()) == PackageManager.PERMISSION_GRANTED;
}
// AppOpsの状態がデフォルトでないならallowedのみtrue
return mode == AppOpsManager.MODE_ALLOWED;
}
最後に、permissionのリクエストです。
これも、通常の方法と違うので注意が必要です。
if (!checkReadStatsPermission()) {
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
}
UsageStatsManagerを使う
ソースコードの中で解説を入れています。
このソースコードは、その日のアプリの使用時間を取得します。
public class UsageStatsClass {
// Log.d()で、このクラスが出力したものだと識別するための名前
private static final String TAG = UsageStatsClass.class.getSimpleName();
// MainActivityのContextを代入
private Context context;
public UsageStatsClass(Context mContext) {
// contextを代入
context = mContext;
}
// UsageStatsというObjectは、一つのアプリの情報(アプリの使用時間など)が入っている
// つまり、1つアプリにつき1つのUsageStatsが割り当てられる
private List<UsageStats> getUsageStatsObject() {
// getSystemService()で、UsageStatsManagerを取得する
// UsageStatsManagerは、アプリの使用情報を取得するためのもの
UsageStatsManager usageStatsManager =
(UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
// 現在時刻をCalendarオブジェクトとして取得する
Calendar calendar = Calendar.getInstance();
// calendarの時刻を午前0時に設定する
// これにより、calendarが内包している時刻情報は、現在時刻から本日の午前0時となる
calendar.set(Calendar.HOUR_OF_DAY, 0);
// queryUsageStats(取得する時間の単位, 取得する時間の始まり、取得する時間の終わり)
// 取得する時間の単位 : 日単位(INTERVAL_DAILY)、週単位(INTERVAL_WEEKLY)、月単位(INTERVAL_MONTHLY)、
// 年単位(INTERVAL_YEARLY)、自動選択(INTERVAL_BEST)がある
//
// 取得する時間の始まり : 取得したいデータの時間帯のスタート地点。今回は、その日の午前0時。
// 取得する時間の終わり : 取得したいデータの時間帯の終わり。今回は、現在時刻。
return usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY,
calendar.getTimeInMillis(),
System.currentTimeMillis());
}
// 外部から実行するための関数
public void readOneDayUsageStats() {
// アプリごとの使用情報をListとして取得
List<UsageStats> usageStats = getUsageStatsObject();
// for文を使用することで、usageStatに一つのアプリの使用情報を取得する
for (UsageStats usageStat : usageStats) {
// もし、そのアプリを一度も使用していない場合は、スキップする
if (usageStat.getTotalTimeInForeground() == 0) {
continue;
}
// Logcatで、取得した情報を出力する
// package name : getPackageName() : そのアプリ固有のID
// total time displayed : getTotalTimeInForeground() : そのアプリが画面上に表示された合計時間
// first time : getFirstTimeStamp() : 取得したデータの始まりの時間をミリ秒で返す
// getStringDate()を使ってミリ秒を人間にわかりやすい形に変換している
// end time : getLastTimeUsed() : 取得したデータの終わりの時間をミリ秒で返す
// getStringDate()を使ってミリ秒を、人間にわかりやすい形に変換している
Log.d(TAG, "packageName: " + usageStat.getPackageName() + "\ttotalTimeDisplayed: " + usageStat.getTotalTimeInForeground()
+ "\tfirstTime: " + getStringDate(usageStat.getFirstTimeStamp()) + "\tlastTime: " + getStringDate(usageStat.getLastTimeUsed()));
}
}
// long型のミリ秒をString型の人間がわかりやすい形に変換する
private String getStringDate(long milliseconds) {
final DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.JAPANESE);
final Date date = new Date(milliseconds);
return df.format(date);
}
}
実行結果
アプリごとの、時間が表示されています。
やったね!
D/UsageStatsClass: packageName: com.huawei.android.launcher totalTimeDisplayed: 3769989 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 15:59:00
D/UsageStatsClass: packageName: jp.naver.line.android totalTimeDisplayed: 805413 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 15:34:36
D/UsageStatsClass: packageName: com.discord totalTimeDisplayed: 4247 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 15:43:05
D/UsageStatsClass: packageName: com.microsoft.office.outlook totalTimeDisplayed: 43011 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 14:19:16
D/UsageStatsClass: packageName: com.google.android.packageinstaller totalTimeDisplayed: 2444 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 15:59:02
D/UsageStatsClass: packageName: com.google.android.apps.photos totalTimeDisplayed: 283917 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 13:38:33
D/UsageStatsClass: packageName: com.spotify.music totalTimeDisplayed: 6267989 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 13:56:21
D/UsageStatsClass: packageName: jp.mineo.app.phone totalTimeDisplayed: 70175 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 13:59:50
D/UsageStatsClass: packageName: com.google.android.apps.translate totalTimeDisplayed: 8170 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 15:04:14
D/UsageStatsClass: packageName: ch.bitspin.timely totalTimeDisplayed: 798142 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 11:17:25
D/UsageStatsClass: packageName: com.android.settings totalTimeDisplayed: 21715 firstTime: 2020/02/27 00:00:02 lastTime: 2020/02/27 14:32:32