package com.fruit.launcher.widgets; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.fruit.launcher.R; import android.app.ActivityManager; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; import android.widget.Toast; public class TaskManagerUtil { public static final float BYTES_PER_M = 1048576.0f; private static final String MEM_TOTAL = "MemTotal:"; private static final String SPLI_REGULAR = "[ ]+"; private static TaskManagerUtil mInstance; private Context mContext; private ActivityManager mActivityMgr; private ArrayList<ITaskManagerUpdate> mTaskWidget; private TaskManagerUtil(Context context) { mContext = context; mActivityMgr = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); mTaskWidget = new ArrayList<ITaskManagerUpdate>(); } public static final TaskManagerUtil getInstance(Context context) { if (mInstance == null) { mInstance = new TaskManagerUtil(context); } return mInstance; } public void addTaskManagerWidget(ITaskManagerUpdate taskManagerWidget) { // TODO Auto-generated method stub mTaskWidget.add(taskManagerWidget); } public void removeTaskManagerWidget(ITaskManagerUpdate taskManagerWidget) { // TODO Auto-generated method stub mTaskWidget.remove(taskManagerWidget); } public final void retrieveMemInfo(boolean bPublishProcess) { new OperateProcessProcedure(mContext, OperateProcessProcedure.OPERATE_RETRIEVE_MEM, bPublishProcess) .run(); } private void publishMemInfo(long totalMem, long availMem) { Iterator<ITaskManagerUpdate> iterator = mTaskWidget.iterator(); while (iterator.hasNext()) { ITaskManagerUpdate iTaskMgr = iterator.next(); if (iTaskMgr != null) { iTaskMgr.onUpdateMemInfo(totalMem, availMem); } } } private void publishProcessList( ArrayList<ApplicationInfo> runningProcessList) { Iterator<ITaskManagerUpdate> iterator = mTaskWidget.iterator(); while (iterator.hasNext()) { ITaskManagerUpdate iTaskMgr = iterator.next(); if (iTaskMgr != null) { iTaskMgr.onUpdateProcess(runningProcessList); } } } public final void freeMemory(Context context, boolean bPublishProcess) { showConfirmDialog(context, bPublishProcess); } private void showConfirmDialog(Context context, boolean bPublishProcess) { // TODO Auto-generated method stub DialogInterface.OnClickListener clickListener; if (bPublishProcess) { clickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub mInstance.startToKillProcess(true); } }; } else { clickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub mInstance.startToKillProcess(false); } }; } new AlertDialog.Builder(context).setTitle(R.string.widget_clean_memory) .setIcon(android.R.drawable.ic_dialog_info) .setMessage(R.string.widget_kill_task) .setPositiveButton(android.R.string.ok, clickListener) .setNegativeButton(android.R.string.cancel, null).show(); } private void startToKillProcess(boolean bPublishProcess) { // TODO Auto-generated method stub new OperateProcessProcedure(mContext, OperateProcessProcedure.OPERATE_KILL_PROCESS, bPublishProcess) .run(); } @SuppressWarnings("deprecation") public void killProcess(ApplicationInfo info) { try { Method method = ActivityManager.class.getDeclaredMethod( "killBackgroundProcesses", new Class[] { String.class }); method.invoke(mActivityMgr, new Object[] { info.packageName }); } catch (Exception e) { e.printStackTrace(); mActivityMgr.restartPackage(info.packageName); } } final class OperateProcessProcedure extends Thread { static final int OPERATE_RETRIEVE_MEM = 0; static final int OPERATE_KILL_PROCESS = 1; static final int OPERATE_MAX = 2; private Context mContext; private ActivityManager mActivityMgr; private List<ApplicationInfo> mInstalledApps; private ArrayList<ApplicationInfo> mRunningProcess; private String mPkgName; private int mOperateType; private ActivityManager.MemoryInfo mMemInfo; private boolean mPublishProcessList; private long mTotalMem; private long mAvailableMem; public OperateProcessProcedure(Context context, int operateType, boolean bPublishProcess) { if (operateType < OPERATE_RETRIEVE_MEM || operateType > OPERATE_KILL_PROCESS) { mOperateType = OPERATE_RETRIEVE_MEM; } else { mOperateType = operateType; } mPublishProcessList = bPublishProcess; mContext = context; mActivityMgr = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); mRunningProcess = new ArrayList<ApplicationInfo>(); mPkgName = mContext.getPackageName(); } @Override public void run() { // TODO Auto-generated method stub if (mInstalledApps != null) { mInstalledApps.clear(); mInstalledApps = null; } mInstalledApps = mContext.getPackageManager() .getInstalledApplications(0); mMemInfo = new ActivityManager.MemoryInfo(); switch (mOperateType) { case OPERATE_KILL_PROCESS: mActivityMgr.getMemoryInfo(mMemInfo); long oldAvailableMem = mMemInfo.availMem; List<ActivityManager.RunningAppProcessInfo> appList = mActivityMgr .getRunningAppProcesses(); Iterator<ActivityManager.RunningAppProcessInfo> iterator = appList .iterator(); while (iterator.hasNext()) { String processName = iterator.next().processName; ApplicationInfo appInfo = getAppInfo(processName); if (appInfo != null) { killProcess(appInfo); } } mActivityMgr.getMemoryInfo(mMemInfo); mAvailableMem = mMemInfo.availMem; if (mAvailableMem > oldAvailableMem) { long freedByte = (mAvailableMem - oldAvailableMem); if (freedByte > (long) BYTES_PER_M) { int freedMem = Math.round(freedByte / BYTES_PER_M); String tip = String .format(mContext .getString(R.string.widget_clean_memory_report), freedMem); Toast.makeText(mContext, tip, Toast.LENGTH_SHORT) .show(); } } else { if (mPublishProcessList) { mPublishProcessList = false; } Toast.makeText( mContext, mContext.getString(R.string.widget_clean_memory_alert), Toast.LENGTH_SHORT).show(); } // do not break here, cause OPERATE_KILL_PROCESS will always // publish memory info case OPERATE_RETRIEVE_MEM: default: try { FileReader fileReader = new FileReader("/proc/meminfo"); BufferedReader bufferedReader = new BufferedReader( fileReader); String line = bufferedReader.readLine(); int total = 0; if (line.startsWith(MEM_TOTAL)) { total = Integer.parseInt(line.split(SPLI_REGULAR)[1]); } bufferedReader.close(); mActivityMgr.getMemoryInfo(mMemInfo); mTotalMem = total * 1024; mAvailableMem = mMemInfo.availMem; publishMemInfo(mTotalMem, mAvailableMem); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } if (mPublishProcessList) { // retrieve current running process list getRunningProcessList(); publishProcessList(mRunningProcess); } } private void getRunningProcessList() { mRunningProcess.clear(); List<ActivityManager.RunningAppProcessInfo> appList = mActivityMgr .getRunningAppProcesses(); Iterator<ActivityManager.RunningAppProcessInfo> iterator = appList .iterator(); while (iterator.hasNext()) { ApplicationInfo appInfo = getAppInfo(iterator.next().processName); if (appInfo != null) { mRunningProcess.add(appInfo); } } } private ApplicationInfo getAppInfo(String processName) { // TODO Auto-generated method stub Iterator<ApplicationInfo> iteratorApps = mInstalledApps.iterator(); ApplicationInfo appInfo = null; while (iteratorApps.hasNext()) { appInfo = iteratorApps.next(); if (appInfo.processName.equals(processName) && !(appInfo.packageName.equals(mPkgName))) { return appInfo; } } return null; } } }