Recently, an application for collecting device information has been made. It's interesting to get the number of application openings and cpu information, so let's go under mark.
1. Get the number of application openings
The class that gets the application information in android devices is the UsageStats.java class (see Official Website) https://developer.android.com/reference/android/app/usage/UsageStatsManager.html):
/**
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package android.app.usage;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Contains usage statistics for an app package for a specific
* time range.
*/
public final class UsageStats implements Parcelable {
/**
* {@hide}
*/
public String mPackageName;
/**
* {@hide}
*/
public long mBeginTimeStamp;
/**
* {@hide}
*/
public long mEndTimeStamp;
/**
* Last time used by the user with an explicit action (notification, activity launch).
* {@hide}
*/
public long mLastTimeUsed;
/**
* {@hide}
*/
public long mTotalTimeInForeground;
/**
* {@hide}
*/
public int mLaunchCount;
/**
* {@hide}
*/
public int mLastEvent;
/**
* {@hide}
*/
public UsageStats() {
}
public UsageStats(UsageStats stats) {
mPackageName = stats.mPackageName;
mBeginTimeStamp = stats.mBeginTimeStamp;
mEndTimeStamp = stats.mEndTimeStamp;
mLastTimeUsed = stats.mLastTimeUsed;
mTotalTimeInForeground = stats.mTotalTimeInForeground;
mLaunchCount = stats.mLaunchCount;
mLastEvent = stats.mLastEvent;
}
public String getPackageName() {
return mPackageName;
}
/**
* Get the beginning of the time range this {@link android.app.usage.UsageStats} represents,
* measured in milliseconds since the epoch.
* <p/>
* See {@link System#currentTimeMillis()}.
*/
public long getFirstTimeStamp() {
return mBeginTimeStamp;
}
/**
* Get the end of the time range this {@link android.app.usage.UsageStats} represents,
* measured in milliseconds since the epoch.
* <p/>
* See {@link System#currentTimeMillis()}.
*/
public long getLastTimeStamp() {
return mEndTimeStamp;
}
/**
* Get the last time this package was used, measured in milliseconds since the epoch.
* <p/>
* See {@link System#currentTimeMillis()}.
*/
public long getLastTimeUsed() {
return mLastTimeUsed;
}
/**
* Get the total time this package spent in the foreground, measured in milliseconds.
*/
public long getTotalTimeInForeground() {
return mTotalTimeInForeground;
}
/**
* Add the statistics from the right {@link UsageStats} to the left. The package name for
* both {@link UsageStats} objects must be the same.
* @param right The {@link UsageStats} object to merge into this one.
* @throws java.lang.IllegalArgumentException if the package names of the two
* {@link UsageStats} objects are different.
*/
public void add(UsageStats right) {
if (!mPackageName.equals(right.mPackageName)) {
throw new IllegalArgumentException("Can't merge UsageStats for package '" +
mPackageName + "' with UsageStats for package '" + right.mPackageName + "'.");
}
if (right.mBeginTimeStamp > mBeginTimeStamp) {
// The incoming UsageStat begins after this one, so use its last time used fields
// as the source of truth.
// We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
// regards to their mEndTimeStamp.
mLastEvent = right.mLastEvent;
mLastTimeUsed = right.mLastTimeUsed;
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
mLaunchCount += right.mLaunchCount;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mPackageName);
dest.writeLong(mBeginTimeStamp);
dest.writeLong(mEndTimeStamp);
dest.writeLong(mLastTimeUsed);
dest.writeLong(mTotalTimeInForeground);
dest.writeInt(mLaunchCount);
dest.writeInt(mLastEvent);
}
public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@Override
public UsageStats createFromParcel(Parcel in) {
UsageStats stats = new UsageStats();
stats.mPackageName = in.readString();
stats.mBeginTimeStamp = in.readLong();
stats.mEndTimeStamp = in.readLong();
stats.mLastTimeUsed = in.readLong();
stats.mTotalTimeInForeground = in.readLong();
stats.mLaunchCount = in.readInt();
stats.mLastEvent = in.readInt();
return stats;
}
@Override
public UsageStats[] newArray(int size) {
return new UsageStats[size];
}
};
}
From the source code, we can see that the list of applications can be obtained through ready-made methods to obtain package name, last time stamp, last time, total foreground time and other information, but there is no way to obtain the number of times of use, which requires reflection.
UsageStatsManager m = (UsageStatsManager) context.getSystemService(USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
long endt = calendar.getTimeInMillis(); //Ending time
calendar.add(Calendar.HOUR_OF_DAY, -1); //The time interval is one day.
long statt = calendar.getTimeInMillis();
List<UsageStats> list = m.queryUsageStats(UsageStatsManager.INTERVAL_BEST, statt, endt);
for (UsageStats stats : list) {
stringBuffer.append(stats.getPackageName() + "##Start time:" + stats.getFirstTimeStamp() + "##Ending time: " + stats.getLastTimeStamp() + "Total running time:" + stats.getTotalTimeInForeground() + "\n");
try {
**int count = stats.getClass().getDeclaredField("mLaunchCount").getInt(stats);**
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
Of course, only the application with system privileges can get the list of applications, and the privileges need to be declared in the manifest file.
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
At that time, there was a problem that the number of open applications must be obtained in activity. It was strange that the number of open applications in other classes was always 0.
2. Obtaining cpu Information
At first, the number of CPUs was obtained by reading the information of'/ proc/stat'file, but on the mobile phone of Exhibition 7.0, it was found that sometimes not all CPUs would print out. Referring to Xia An Rabbit, it was found that some CPUs were dormant, and then it was found that the number of CPUs under the directory of'/ sys/devices/system/cpu/'could be obtained by looking up the number of CPUs under the directory of'/sys/devices/system/cpu/'. Quantity to view device CPU core.
Continuing with cd to cpu3, you can see that sometimes there is no current_freq file, which should be really dormant.
The code to get the number of CPUs is as follows:
public static int getNumCores() {
//Private Class to display only CPU devices in the directory listing
class CpuFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
//Check if filename is "cpu", followed by a single digit number
if (Pattern.matches("cpu[0-9]+", pathname.getName())) {
return true;
}
return false;
}
}
try {
//Get directory containing CPU info
File dir = new File("/sys/devices/system/cpu/");
//Filter to only list the devices we care about
File[] files = dir.listFiles(new CpuFilter());
Trace.d(TAG, "CPU Count: " + files.length);
//Return the number of cores (virtual CPU devices)
return files.length;
} catch (Exception e) {
//Print exception
Trace.d(TAG, "CPU Count: Failed.");
e.printStackTrace();
//Default to return 1 core
return 1;
}
}