version:
update:2021.03.19 fix:修改上传应用信息为排除出厂的app和三方app add:
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package com.mjsheng.myappstore.statistics;
|
||||
|
||||
import android.app.usage.UsageStats;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
|
||||
public class AppInformation {
|
||||
private UsageStats usageStats;
|
||||
private String packageName;
|
||||
private String label;
|
||||
private Drawable Icon;
|
||||
private long UsedTimebyDay; //milliseconds
|
||||
private Context context;
|
||||
private int times;
|
||||
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public AppInformation(UsageStats usageStats, Context context) {
|
||||
this.usageStats = usageStats;
|
||||
this.context = context;
|
||||
|
||||
try {
|
||||
GenerateInfo();
|
||||
} catch (PackageManager.NameNotFoundException | IllegalAccessException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
private void GenerateInfo() throws PackageManager.NameNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
this.packageName = usageStats.getPackageName();
|
||||
if (this.packageName != null && !this.packageName.equals("")) {
|
||||
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(this.packageName, 0);
|
||||
this.label = (String) packageManager.getApplicationLabel(applicationInfo);
|
||||
this.UsedTimebyDay = usageStats.getTotalTimeInForeground();
|
||||
this.times = (Integer) usageStats.getClass().getDeclaredField("mLaunchCount").get(usageStats);
|
||||
|
||||
if (this.UsedTimebyDay > 0) {
|
||||
this.Icon = applicationInfo.loadIcon(packageManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UsageStats getUsageStats() {
|
||||
return usageStats;
|
||||
}
|
||||
|
||||
public int getTimes() {
|
||||
return times;
|
||||
}
|
||||
|
||||
public void setTimes(int times) {
|
||||
this.times = times;
|
||||
}
|
||||
|
||||
public void setUsedTimebyDay(long usedTimebyDay) {
|
||||
this.UsedTimebyDay = usedTimebyDay;
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
return Icon;
|
||||
}
|
||||
|
||||
public long getUsedTimebyDay() {
|
||||
return UsedTimebyDay;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
private long timeStampMoveToForeground = -1;
|
||||
|
||||
private long timeStampMoveToBackGround = -1;
|
||||
|
||||
|
||||
public void setTimeStampMoveToForeground(long timeStampMoveToForeground) {
|
||||
// if (timeStampMoveToForeground > bootTime()){
|
||||
// timesPlusPlus();
|
||||
// }
|
||||
this.timeStampMoveToForeground = timeStampMoveToForeground;
|
||||
}
|
||||
|
||||
public void timesPlusPlus(){
|
||||
times++;
|
||||
}
|
||||
|
||||
public void setTimeStampMoveToBackGround(long timeStampMoveToBackGround) {
|
||||
this.timeStampMoveToBackGround = timeStampMoveToBackGround;
|
||||
}
|
||||
|
||||
public long getTimeStampMoveToBackGround() {
|
||||
return timeStampMoveToBackGround;
|
||||
}
|
||||
|
||||
public long getTimeStampMoveToForeground() {
|
||||
return timeStampMoveToForeground;
|
||||
}
|
||||
|
||||
public void calculateRunningTime() {
|
||||
|
||||
if (timeStampMoveToForeground < 0 || timeStampMoveToBackGround < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeStampMoveToBackGround > timeStampMoveToForeground) {
|
||||
UsedTimebyDay += (timeStampMoveToBackGround - timeStampMoveToForeground);
|
||||
timeStampMoveToForeground = -1;
|
||||
timeStampMoveToBackGround = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 返回开机时间,单位微妙
|
||||
public static long bootTime() {
|
||||
return System.currentTimeMillis() - SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package com.mjsheng.myappstore.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.mjsheng.myappstore.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