android采集应用打开次数和cpu信息

最近做了一个采集设备信息的应用,其中获取应用打开次数以及cpu信息还是挺有意思的,所以在此mark下吧。

一、获取应用打开次数

获取android设备中应用信息的类是UsageStats.java类(官网见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];
        }
    };
}

从源码中可以看出,获取应用的列表可以就可以通过现成的方法获取包名、上次使用时间戳、上次使用时间、总的前台使用时间等信息,但却没有获取使用次数的方法,这就需要使用反射了。

UsageStatsManager m = (UsageStatsManager) context.getSystemService(USAGE_STATS_SERVICE);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(new Date());
                        long endt = calendar.getTimeInMillis(); //结束时间
                        calendar.add(Calendar.HOUR_OF_DAY, -1); //时间间隔为一天
                        long statt = calendar.getTimeInMillis();
                        List<UsageStats> list = m.queryUsageStats(UsageStatsManager.INTERVAL_BEST, statt, endt);
                        for (UsageStats stats : list) {
                            stringBuffer.append(stats.getPackageName() + "##开始时间:" + stats.getFirstTimeStamp() + "##结束时间:" + stats.getLastTimeStamp() + "总运行时间:" + stats.getTotalTimeInForeground() + "\n");
                            try {
                                **int count = stats.getClass().getDeclaredField("mLaunchCount").getInt(stats);**
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (NoSuchFieldException e) {
                                e.printStackTrace();
                            }
                        }

当然啦,还是只有系统权限的应用才能获取到应用列表,同时需要在manifest文件中声明权限

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

当时出现了一个问题,那就是必须在activity中才能获取到应用打开次数,在其他类里面获取到的次数总是为0,还奇怪耶。

二、 获取cpu信息

这里写图片描述
开始是通过读取“/proc/stat”文件的信息来获取cpu数目的,但是在展讯7.0手机上发现,有些时候并不是所有cpu都会打印出来,参考了下安兔兔,发现有些cpu在休眠,又查找了下,发现可以通过“/sys/devices/system/cpu/”目录下cpu的数量来查看设备cpu核数。
这里写图片描述
继续cd到cpu3下可以看出有时没有current_freq文件,这应该是真的在休眠了吧。
这里写图片描述

获取cpu数量的代码如下:

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;
        }
    }

猜你喜欢

转载自blog.csdn.net/u013795543/article/details/70195462