PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/example/appmonitor/AppMonitor.java

https://bitbucket.org/yihuaqi/appmonitor
Java | 269 lines | 166 code | 35 blank | 68 comment | 10 complexity | 0f171f7511b26da44ce34f9b359909ad MD5 | raw file
  1. package com.example.appmonitor;
  2. import java.io.BufferedReader;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. import java.lang.reflect.InvocationTargetException;
  6. import java.text.SimpleDateFormat;
  7. import java.util.ArrayList;
  8. import java.util.Date;
  9. import java.util.HashMap;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import android.app.Activity;
  13. import android.app.ActivityManager;
  14. import android.app.ActivityManager.RunningAppProcessInfo;
  15. import android.content.Context;
  16. import android.content.pm.ApplicationInfo;
  17. import android.content.pm.PackageManager;
  18. import android.graphics.drawable.Drawable;
  19. import android.net.TrafficStats;
  20. import android.os.SystemClock;
  21. import android.util.Log;
  22. /**
  23. * Utils class for getting app status.
  24. * @author yihuaqi
  25. *
  26. */
  27. public class AppMonitor {
  28. private final static String TAG="AppMonitor";
  29. /**
  30. * HashMap that stores AppStatus of apps that are installed.
  31. * Key: processName of the app.
  32. * Value: AppStatus
  33. */
  34. private static HashMap<String,AppStatus> mAppStatus = new HashMap<String,AppStatus>();
  35. /**
  36. * HashMap that stores RunningAppProcessInfo of apps that are running.
  37. * Key: procesName of the app
  38. * Value: RunningAppProcessInfo
  39. */
  40. private static HashMap<String, RunningAppProcessInfo> mRunningAppProcessInfo = new HashMap<String, ActivityManager.RunningAppProcessInfo>();
  41. /**
  42. * Convert the HashMap that stores AppStatus into an List, and sort it so that
  43. * the active apps are before the inactive.
  44. * @return
  45. */
  46. public static List<AppStatus> getAppStatus(){
  47. List<AppStatus> result = new ArrayList<AppStatus>(mAppStatus.values());
  48. for(int i = 0; i < result.size(); i++){
  49. AppStatus curAppStatus = result.get(i);
  50. if(curAppStatus.getIsRunning()){
  51. result.remove(i);
  52. result.add(0,curAppStatus);
  53. }
  54. }
  55. return result;
  56. }
  57. /**
  58. *
  59. * @param mContext
  60. * @return A list of RunningAppProcessInfo
  61. */
  62. public static List<ActivityManager.RunningAppProcessInfo> getRunningApps(Context mContext){
  63. ActivityManager am = (ActivityManager) mContext.getSystemService(Activity.ACTIVITY_SERVICE);
  64. return am.getRunningAppProcesses();
  65. }
  66. /**
  67. *
  68. * @param mContext
  69. * @return A list of ApplicationInfo that are installed
  70. */
  71. public static List<ApplicationInfo> getInstalledApps(Context mContext){
  72. PackageManager pm = mContext.getPackageManager();
  73. return pm.getInstalledApplications(PackageManager.GET_META_DATA);
  74. }
  75. public static long getTotalRxBytes(){
  76. Log.d("AppMonitor", "Total Rx:"+TrafficStats.getTotalRxBytes());
  77. return TrafficStats.getTotalRxBytes();
  78. }
  79. public static long getTotalTxBytes(){
  80. Log.d("AppMonitor", "Total Tx:"+TrafficStats.getTotalTxBytes());
  81. return TrafficStats.getTotalTxBytes();
  82. }
  83. /**
  84. * Given a pid, return the start date of this process.
  85. * @param pid
  86. * @return
  87. * @throws IOException
  88. */
  89. private static String getStartDate(final int pid) throws IOException {
  90. long startTime = getStartTimeMills(pid);
  91. long startTimeMills =System.currentTimeMillis()+startTime-SystemClock.elapsedRealtime();
  92. Log.d("AppMonitor","Start time:"+ startTime);
  93. return getFormattedDate(startTimeMills);
  94. }
  95. /**
  96. * Given a time in millsecond, return a formatted date.
  97. * @param timeMills
  98. * @return
  99. */
  100. public static String getFormattedDate(long timeMills){
  101. Date date = new Date();
  102. date.setTime(timeMills);
  103. String formattedDate=new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy").format(date);
  104. return formattedDate;
  105. }
  106. /**
  107. * Initialize a constant from system config
  108. */
  109. private static long tck;
  110. static{
  111. try {
  112. final int tckName = Class.forName("libcore.io.OsConstants").getField("_SC_CLK_TCK").getInt(null);
  113. final Object os = Class.forName("libcore.io.Libcore").getField("os").get(null);
  114. tck = (Long)os.getClass().getMethod("sysconf", Integer.TYPE).invoke(os, tckName);
  115. } catch (IllegalAccessException e) {
  116. // TODO Auto-generated catch block
  117. e.printStackTrace();
  118. } catch (IllegalArgumentException e) {
  119. // TODO Auto-generated catch block
  120. e.printStackTrace();
  121. } catch (InvocationTargetException e) {
  122. // TODO Auto-generated catch block
  123. e.printStackTrace();
  124. } catch (NoSuchMethodException e) {
  125. // TODO Auto-generated catch block
  126. e.printStackTrace();
  127. } catch (NoSuchFieldException e) {
  128. // TODO Auto-generated catch block
  129. e.printStackTrace();
  130. } catch (ClassNotFoundException e) {
  131. // TODO Auto-generated catch block
  132. e.printStackTrace();
  133. }
  134. }
  135. /**
  136. * Given a pid, return the uptime of the process with the pid.
  137. * @param pid
  138. * @return
  139. * @throws IOException
  140. */
  141. public static long getStartTimeMills(final int pid) throws IOException {
  142. final String path = "/proc/" + pid + "/stat";
  143. final BufferedReader reader = new BufferedReader(new FileReader(path));
  144. final String stat;
  145. try {
  146. stat = reader.readLine();
  147. } finally {
  148. reader.close();
  149. }
  150. final String field2End = ") ";
  151. final String fieldSep = " ";
  152. final int fieldStartTime = 20;
  153. final int msInSec = 1000;
  154. try {
  155. final String[] fields = stat.substring(stat.lastIndexOf(field2End)).split(fieldSep);
  156. final long t = Long.parseLong(fields[fieldStartTime]);
  157. return t * msInSec / tck;
  158. } catch (final NumberFormatException e) {
  159. throw new IOException(e);
  160. } catch (final IndexOutOfBoundsException e) {
  161. throw new IOException(e);
  162. }
  163. }
  164. /**
  165. * Update the AppStatus.
  166. * @param context
  167. */
  168. public static void updateAppStatus(Context context) {
  169. updateInstalledAppList(context);
  170. updateRunningProcessList(context);
  171. }
  172. /**
  173. * Update the running status, opened time and closed time of apps.
  174. * @param context
  175. */
  176. private static void updateRunningProcessList(Context context) {
  177. List<RunningAppProcessInfo> infos = getRunningApps(context);
  178. HashMap<String, RunningAppProcessInfo> currentInfosMap = new HashMap<String, ActivityManager.RunningAppProcessInfo>();
  179. for(RunningAppProcessInfo rapi:infos){
  180. currentInfosMap.put(rapi.processName, rapi);
  181. }
  182. for(Iterator<RunningAppProcessInfo> it = mRunningAppProcessInfo.values().iterator(); it.hasNext();){
  183. RunningAppProcessInfo prevInfo = it.next();
  184. if(!currentInfosMap.containsKey(prevInfo.processName)){
  185. mAppStatus.get(prevInfo.processName).setIsRunning(false);
  186. mAppStatus.get(prevInfo.processName).setClosedTime(getFormattedDate(System.currentTimeMillis()));
  187. it.remove();
  188. } else{
  189. currentInfosMap.remove(prevInfo.processName);
  190. }
  191. }
  192. for(RunningAppProcessInfo curInfo: currentInfosMap.values()){
  193. mRunningAppProcessInfo.put(curInfo.processName, curInfo);
  194. if(mAppStatus.get(curInfo.processName)!=null){
  195. mAppStatus.get(curInfo.processName).setIsRunning(true);
  196. try {
  197. mAppStatus.get(curInfo.processName).setOpenedTime(getStartDate(curInfo.pid));
  198. } catch (IOException e) {
  199. mAppStatus.get(curInfo.processName).setOpenedTime("N/A");
  200. e.printStackTrace();
  201. }
  202. mAppStatus.get(curInfo.processName).setClosedTime("N/A");
  203. } else {
  204. Log.d(TAG, "Null App Status:"+curInfo.processName);
  205. }
  206. }
  207. Log.d(TAG, "RunningApps:"+mRunningAppProcessInfo.size());
  208. }
  209. /**
  210. * Update the AppStatus of all the installed apps.
  211. * @param context
  212. */
  213. private static void updateInstalledAppList(Context context) {
  214. List<ApplicationInfo> infos = getInstalledApps(context);
  215. for(ApplicationInfo ai:infos){
  216. if(!mAppStatus.containsKey(ai.processName)){
  217. AppStatus newAppStatus = new AppStatus();
  218. newAppStatus.setApplicationInfo(ai);
  219. newAppStatus.setLabel(getLabel(context,ai));
  220. newAppStatus.setIcon(getIcon(context,ai));
  221. mAppStatus.put(ai.processName, newAppStatus);
  222. }
  223. }
  224. Log.d(TAG, "Installed Apps:"+mAppStatus.size());
  225. }
  226. private static String getLabel(Context context,ApplicationInfo ai){
  227. PackageManager pm = context.getPackageManager();
  228. return (String) ai.loadLabel(pm);
  229. }
  230. private static Drawable getIcon(Context context,ApplicationInfo ai){
  231. PackageManager pm = context.getPackageManager();
  232. return ai.loadIcon(pm);
  233. }
  234. }