/src/com/example/appmonitor/AppMonitor.java
Java | 269 lines | 166 code | 35 blank | 68 comment | 10 complexity | 0f171f7511b26da44ce34f9b359909ad MD5 | raw file
- package com.example.appmonitor;
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.io.IOException;
- import java.lang.reflect.InvocationTargetException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import android.app.Activity;
- import android.app.ActivityManager;
- import android.app.ActivityManager.RunningAppProcessInfo;
- import android.content.Context;
- import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageManager;
- import android.graphics.drawable.Drawable;
- import android.net.TrafficStats;
- import android.os.SystemClock;
- import android.util.Log;
- /**
- * Utils class for getting app status.
- * @author yihuaqi
- *
- */
- public class AppMonitor {
-
- private final static String TAG="AppMonitor";
-
- /**
- * HashMap that stores AppStatus of apps that are installed.
- * Key: processName of the app.
- * Value: AppStatus
- */
- private static HashMap<String,AppStatus> mAppStatus = new HashMap<String,AppStatus>();
- /**
- * HashMap that stores RunningAppProcessInfo of apps that are running.
- * Key: procesName of the app
- * Value: RunningAppProcessInfo
- */
- private static HashMap<String, RunningAppProcessInfo> mRunningAppProcessInfo = new HashMap<String, ActivityManager.RunningAppProcessInfo>();
-
- /**
- * Convert the HashMap that stores AppStatus into an List, and sort it so that
- * the active apps are before the inactive.
- * @return
- */
- public static List<AppStatus> getAppStatus(){
- List<AppStatus> result = new ArrayList<AppStatus>(mAppStatus.values());
- for(int i = 0; i < result.size(); i++){
- AppStatus curAppStatus = result.get(i);
- if(curAppStatus.getIsRunning()){
- result.remove(i);
- result.add(0,curAppStatus);
- }
- }
- return result;
- }
-
- /**
- *
- * @param mContext
- * @return A list of RunningAppProcessInfo
- */
- public static List<ActivityManager.RunningAppProcessInfo> getRunningApps(Context mContext){
- ActivityManager am = (ActivityManager) mContext.getSystemService(Activity.ACTIVITY_SERVICE);
-
- return am.getRunningAppProcesses();
- }
-
- /**
- *
- * @param mContext
- * @return A list of ApplicationInfo that are installed
- */
- public static List<ApplicationInfo> getInstalledApps(Context mContext){
- PackageManager pm = mContext.getPackageManager();
-
- return pm.getInstalledApplications(PackageManager.GET_META_DATA);
- }
-
-
- public static long getTotalRxBytes(){
- Log.d("AppMonitor", "Total Rx:"+TrafficStats.getTotalRxBytes());
- return TrafficStats.getTotalRxBytes();
- }
- public static long getTotalTxBytes(){
- Log.d("AppMonitor", "Total Tx:"+TrafficStats.getTotalTxBytes());
- return TrafficStats.getTotalTxBytes();
- }
-
- /**
- * Given a pid, return the start date of this process.
- * @param pid
- * @return
- * @throws IOException
- */
- private static String getStartDate(final int pid) throws IOException {
- long startTime = getStartTimeMills(pid);
- long startTimeMills =System.currentTimeMillis()+startTime-SystemClock.elapsedRealtime();
- Log.d("AppMonitor","Start time:"+ startTime);
-
- return getFormattedDate(startTimeMills);
- }
-
- /**
- * Given a time in millsecond, return a formatted date.
- * @param timeMills
- * @return
- */
- public static String getFormattedDate(long timeMills){
- Date date = new Date();
- date.setTime(timeMills);
- String formattedDate=new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").format(date);
- return formattedDate;
- }
-
- /**
- * Initialize a constant from system config
- */
- private static long tck;
- static{
-
- try {
- final int tckName = Class.forName("libcore.io.OsConstants").getField("_SC_CLK_TCK").getInt(null);
- final Object os = Class.forName("libcore.io.Libcore").getField("os").get(null);
- tck = (Long)os.getClass().getMethod("sysconf", Integer.TYPE).invoke(os, tckName);
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (NoSuchFieldException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- /**
- * Given a pid, return the uptime of the process with the pid.
- * @param pid
- * @return
- * @throws IOException
- */
- public static long getStartTimeMills(final int pid) throws IOException {
- final String path = "/proc/" + pid + "/stat";
- final BufferedReader reader = new BufferedReader(new FileReader(path));
- final String stat;
- try {
- stat = reader.readLine();
- } finally {
- reader.close();
- }
- final String field2End = ") ";
- final String fieldSep = " ";
- final int fieldStartTime = 20;
- final int msInSec = 1000;
- try {
-
- final String[] fields = stat.substring(stat.lastIndexOf(field2End)).split(fieldSep);
- final long t = Long.parseLong(fields[fieldStartTime]);
-
- return t * msInSec / tck;
- } catch (final NumberFormatException e) {
- throw new IOException(e);
- } catch (final IndexOutOfBoundsException e) {
- throw new IOException(e);
- }
- }
-
- /**
- * Update the AppStatus.
- * @param context
- */
- public static void updateAppStatus(Context context) {
- updateInstalledAppList(context);
- updateRunningProcessList(context);
- }
- /**
- * Update the running status, opened time and closed time of apps.
- * @param context
- */
- private static void updateRunningProcessList(Context context) {
- List<RunningAppProcessInfo> infos = getRunningApps(context);
- HashMap<String, RunningAppProcessInfo> currentInfosMap = new HashMap<String, ActivityManager.RunningAppProcessInfo>();
- for(RunningAppProcessInfo rapi:infos){
- currentInfosMap.put(rapi.processName, rapi);
- }
- for(Iterator<RunningAppProcessInfo> it = mRunningAppProcessInfo.values().iterator(); it.hasNext();){
- RunningAppProcessInfo prevInfo = it.next();
- if(!currentInfosMap.containsKey(prevInfo.processName)){
- mAppStatus.get(prevInfo.processName).setIsRunning(false);
- mAppStatus.get(prevInfo.processName).setClosedTime(getFormattedDate(System.currentTimeMillis()));
- it.remove();
- } else{
- currentInfosMap.remove(prevInfo.processName);
- }
- }
- for(RunningAppProcessInfo curInfo: currentInfosMap.values()){
- mRunningAppProcessInfo.put(curInfo.processName, curInfo);
- if(mAppStatus.get(curInfo.processName)!=null){
- mAppStatus.get(curInfo.processName).setIsRunning(true);
- try {
- mAppStatus.get(curInfo.processName).setOpenedTime(getStartDate(curInfo.pid));
-
- } catch (IOException e) {
- mAppStatus.get(curInfo.processName).setOpenedTime("N/A");
- e.printStackTrace();
- }
- mAppStatus.get(curInfo.processName).setClosedTime("N/A");
- } else {
- Log.d(TAG, "Null App Status:"+curInfo.processName);
- }
- }
- Log.d(TAG, "RunningApps:"+mRunningAppProcessInfo.size());
-
- }
- /**
- * Update the AppStatus of all the installed apps.
- * @param context
- */
- private static void updateInstalledAppList(Context context) {
- List<ApplicationInfo> infos = getInstalledApps(context);
- for(ApplicationInfo ai:infos){
- if(!mAppStatus.containsKey(ai.processName)){
- AppStatus newAppStatus = new AppStatus();
- newAppStatus.setApplicationInfo(ai);
- newAppStatus.setLabel(getLabel(context,ai));
- newAppStatus.setIcon(getIcon(context,ai));
- mAppStatus.put(ai.processName, newAppStatus);
- }
- }
- Log.d(TAG, "Installed Apps:"+mAppStatus.size());
-
- }
-
- private static String getLabel(Context context,ApplicationInfo ai){
- PackageManager pm = context.getPackageManager();
- return (String) ai.loadLabel(pm);
- }
-
- private static Drawable getIcon(Context context,ApplicationInfo ai){
- PackageManager pm = context.getPackageManager();
- return ai.loadIcon(pm);
- }
- }