version:1.0
update:2021-10-13 18:52:13 fix:去除okgo,rxAndroid1,优化依赖 add:切换到奥乐云平台
This commit is contained in:
283
app/src/main/java/com/aoleyun/sn/statistics/StatisticsInfo.java
Normal file
283
app/src/main/java/com/aoleyun/sn/statistics/StatisticsInfo.java
Normal file
@@ -0,0 +1,283 @@
|
||||
package com.aoleyun.sn.statistics;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.app.usage.UsageStats;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static com.aoleyun.sn.statistics.AppInformation.bootTime;
|
||||
|
||||
|
||||
public class StatisticsInfo {
|
||||
|
||||
final public static int DAY = 0;
|
||||
final public static int WEEK = 1;
|
||||
final public static int MONTH = 2;
|
||||
final public static int YEAR = 3;
|
||||
|
||||
private ArrayList<AppInformation> ShowList;
|
||||
private ArrayList<AppInformation> AppInfoList;
|
||||
private List<UsageStats> result;
|
||||
private long totalTime;
|
||||
private int totalTimes;
|
||||
private int style;
|
||||
|
||||
public StatisticsInfo(Context context) {
|
||||
try {
|
||||
this.style = 0;
|
||||
setUsageStatsList(context);
|
||||
setShowList();
|
||||
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public StatisticsInfo(Context context, int style) {
|
||||
try {
|
||||
this.style = style;
|
||||
setUsageStatsList(context);
|
||||
setShowList();
|
||||
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//将次数和时间为0的应用信息过滤掉
|
||||
private void setShowList() {
|
||||
this.ShowList = new ArrayList<>();
|
||||
|
||||
totalTime = 0;
|
||||
|
||||
for (int i = 0; i < AppInfoList.size(); i++) {
|
||||
if (AppInfoList.get(i).getUsedTimebyDay() > 0) { //&& AppInfoList.get(i).getTimes() > 0) {
|
||||
|
||||
this.ShowList.add(AppInfoList.get(i));
|
||||
totalTime += AppInfoList.get(i).getUsedTimebyDay();
|
||||
totalTimes += AppInfoList.get(i).getTimes();
|
||||
}
|
||||
}
|
||||
|
||||
//将显示列表中的应用按显示顺序排序
|
||||
for (int i = 0; i < this.ShowList.size() - 1; i++) {
|
||||
for (int j = 0; j < this.ShowList.size() - i - 1; j++) {
|
||||
if (this.ShowList.get(j).getUsedTimebyDay() < this.ShowList.get(j + 1).getUsedTimebyDay()) {
|
||||
AppInformation temp = this.ShowList.get(j);
|
||||
this.ShowList.set(j, this.ShowList.get(j + 1));
|
||||
this.ShowList.set(j + 1, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//统计当天的应用使用时间
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void setUsageStatsList(Context context) throws NoSuchFieldException {
|
||||
UsageStatsManager m = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
|
||||
this.AppInfoList = new ArrayList<>();
|
||||
if (m != null) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
long now = calendar.getTimeInMillis();
|
||||
long begintime = getBeginTime();
|
||||
if (style == DAY) {
|
||||
this.result = m.queryUsageStats(UsageStatsManager.INTERVAL_BEST, begintime, now);
|
||||
AppInfoList = getAccurateDailyStatsList(context, result, m, begintime, now);
|
||||
} else {
|
||||
if (style == WEEK)
|
||||
this.result = m.queryUsageStats(UsageStatsManager.INTERVAL_WEEKLY, begintime, now);
|
||||
else if (style == MONTH)
|
||||
this.result = m.queryUsageStats(UsageStatsManager.INTERVAL_MONTHLY, begintime, now);
|
||||
else if (style == YEAR)
|
||||
this.result = m.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, begintime, now);
|
||||
else {
|
||||
this.result = m.queryUsageStats(UsageStatsManager.INTERVAL_BEST, begintime, now);
|
||||
}
|
||||
|
||||
List<UsageStats> Mergeresult = MergeList(this.result);
|
||||
for (UsageStats usageStats : Mergeresult) {
|
||||
this.AppInfoList.add(new AppInformation(usageStats, context));
|
||||
}
|
||||
calculateLaunchTimesAfterBootOn(context, AppInfoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据UsageEvents来对当天的操作次数和开机后运行时间来进行精确计算
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private ArrayList<AppInformation> getAccurateDailyStatsList(Context context, List<UsageStats> result, UsageStatsManager m, long begintime, long now) {
|
||||
//针对每个packageName建立一个 使用信息
|
||||
HashMap<String, AppInformation> mapData = new HashMap<>();
|
||||
//得到包名
|
||||
for (UsageStats stats : result) {
|
||||
if (stats.getLastTimeUsed() > begintime && stats.getTotalTimeInForeground() > 0) {
|
||||
if (mapData.get(stats.getPackageName()) == null) {
|
||||
AppInformation information = new AppInformation(stats, context);
|
||||
//重置总运行时间 开机操作次数
|
||||
information.setTimes(0);
|
||||
information.setUsedTimebyDay(0);
|
||||
mapData.put(stats.getPackageName(), information);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//这个是相对比较精确的
|
||||
long bootTime = bootTime();
|
||||
UsageEvents events = m.queryEvents(bootTime, now);
|
||||
|
||||
UsageEvents.Event e = new UsageEvents.Event();
|
||||
while (events.hasNextEvent()) {
|
||||
events.getNextEvent(e);
|
||||
String packageName = e.getPackageName();
|
||||
|
||||
AppInformation information = mapData.get(packageName);
|
||||
if (information == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//这里在同时计算开机后的操作次数和运行时间,所以如果获取到的时间戳是昨天的话就得过滤掉 continue
|
||||
|
||||
if (e.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
|
||||
information.timesPlusPlus();
|
||||
if (e.getTimeStamp() < begintime){
|
||||
continue;
|
||||
}
|
||||
information.setTimeStampMoveToForeground(e.getTimeStamp());
|
||||
} else if (e.getEventType() == UsageEvents.Event.MOVE_TO_BACKGROUND) {
|
||||
if (e.getTimeStamp() < begintime){
|
||||
continue;
|
||||
}
|
||||
information.setTimeStampMoveToBackGround(e.getTimeStamp());
|
||||
//当前应用是在昨天进入的前台,0点后转入了后台,所以会先得到MOVE_TO_BACKGROUND 的timeStamp
|
||||
if (information.getTimeStampMoveToForeground() < 0) {
|
||||
//从今天开始计算即可
|
||||
information.setTimeStampMoveToForeground(begintime);
|
||||
}
|
||||
}
|
||||
information.calculateRunningTime();
|
||||
}
|
||||
|
||||
//再计算一次当前应用的运行时间,因为当前应用,最后得不到MOVE_TO_BACKGROUND 的timeStamp
|
||||
AppInformation information = mapData.get(context.getPackageName());
|
||||
information.setTimeStampMoveToBackGround(now);
|
||||
information.calculateRunningTime();
|
||||
|
||||
return new ArrayList<>(mapData.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据UsageEvents 精确计算APP开机的启动(activity打开的)次数
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private void calculateLaunchTimesAfterBootOn(Context context, List<AppInformation> AppInfoList) {
|
||||
|
||||
UsageStatsManager m = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
|
||||
if (m == null || AppInfoList == null || AppInfoList.size() < 1) {
|
||||
return;
|
||||
}
|
||||
//针对每个packageName建立一个 使用信息
|
||||
HashMap<String, AppInformation> mapData = new HashMap<>();
|
||||
|
||||
UsageEvents events = m.queryEvents(bootTime(), System.currentTimeMillis());
|
||||
for (AppInformation information : AppInfoList) {
|
||||
mapData.put(information.getPackageName(), information);
|
||||
information.setTimes(0);
|
||||
}
|
||||
|
||||
UsageEvents.Event e = new UsageEvents.Event();
|
||||
while (events.hasNextEvent()) {
|
||||
events.getNextEvent(e);
|
||||
String packageName = e.getPackageName();
|
||||
AppInformation information = mapData.get(packageName);
|
||||
if (information == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
|
||||
information.timesPlusPlus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getBeginTime() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
long begintime;
|
||||
if (style == WEEK) {
|
||||
//int weekDay = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
calendar.add(Calendar.DATE, -7);
|
||||
begintime = calendar.getTimeInMillis();
|
||||
} else if (style == MONTH) {
|
||||
//int mounthDay = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
calendar.add(Calendar.DATE, -30);
|
||||
begintime = calendar.getTimeInMillis();
|
||||
} else if (style == YEAR) {
|
||||
calendar.add(Calendar.YEAR, -1);
|
||||
begintime = calendar.getTimeInMillis();
|
||||
} else {
|
||||
//剩下的输入均显示当天的数据
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = calendar.get(Calendar.MINUTE);
|
||||
int second = calendar.get(Calendar.SECOND);
|
||||
|
||||
calendar.add(Calendar.SECOND, -1 * second);
|
||||
calendar.add(Calendar.MINUTE, -1 * minute);
|
||||
calendar.add(Calendar.HOUR, -1 * hour);
|
||||
begintime = calendar.getTimeInMillis();
|
||||
|
||||
}
|
||||
return begintime;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private List<UsageStats> MergeList(List<UsageStats> result) {
|
||||
List<UsageStats> Mergeresult = new ArrayList<>();
|
||||
long begintime;
|
||||
begintime = getBeginTime();
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
if (result.get(i).getLastTimeUsed() > begintime) {
|
||||
int num = FoundUsageStats(Mergeresult, result.get(i));
|
||||
if (num >= 0) {
|
||||
UsageStats u = Mergeresult.get(num);
|
||||
u.add(result.get(i));
|
||||
Mergeresult.set(num, u);
|
||||
} else Mergeresult.add(result.get(i));
|
||||
}
|
||||
}
|
||||
return Mergeresult;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private int FoundUsageStats(List<UsageStats> Mergeresult, UsageStats usageStats) {
|
||||
for (int i = 0; i < Mergeresult.size(); i++) {
|
||||
if (Mergeresult.get(i).getPackageName().equals(usageStats.getPackageName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
public long getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
public int getTotalTimes() {
|
||||
return totalTimes;
|
||||
}
|
||||
|
||||
public ArrayList<AppInformation> getShowList() {
|
||||
return ShowList;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user