package com.sandro.mamanger; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.sandro.ImageTrans.MainApp; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.os.Handler; import android.os.Message; import android.util.Log; /** * 应用开启后同时启动定时任务和logcat任务线程监控屏幕 * 如果logcat发现到了应用启动则会关闭定时任务线程 * 如果定时任务发现了n次应用启动,没有比关闭说明log线程没能监控到应用启动,此时会关闭log线程 * @author sandrocheng * */ public class WindowMonitor { private static WindowMonitor manager; private LogCatThread logCatThread; private Object monitorLock = new Object(); private MonitorListener monitorListener; private static final int MSG_LOOP = 100; /** * 监控模式:双线程监控 */ private static final int MONITOR_PATTERN_BOATH = 0; /** * 监控模式:log线程监控 */ private static final int MONITOR_PATTERN_LOGCAT = 1; /** * 监控模式:定时监控 */ private static final int MONITOR_PATTERN_TIMER = 2; /** * 监控模式 */ private int monitorPattern = MONITOR_PATTERN_BOATH; private ActivityManager activityManager; /** * 当timeCount >5 关闭locat线程 */ private int timeCount = 0; private Handler mHandler = new Handler(MainApp.getContext().getMainLooper()){ @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_LOOP: synchronized (monitorLock) { List<RunningTaskInfo> rtinfos = activityManager.getRunningTasks(1); if(monitorPattern != MONITOR_PATTERN_LOGCAT){ if(rtinfos.size()>0){ RunningTaskInfo info = rtinfos.get(0); String packageName = info.baseActivity.getPackageName(); callBackListener(MONITOR_PATTERN_TIMER,packageName); } if(timeCount>5){ monitorPattern = MONITOR_PATTERN_TIMER; if(logCatThread!=null){ logCatThread.destory(); logCatThread = null; } }else{ timeCount ++; } this.sendEmptyMessageDelayed(MSG_LOOP, 1000l); } } break; default: super.handleMessage(msg); break; } } }; private WindowMonitor(){ activityManager = (ActivityManager) MainApp.getContext().getSystemService(Activity.ACTIVITY_SERVICE); } public static WindowMonitor getIntance(){ if(manager == null){ manager = new WindowMonitor(); } return manager; } /** * 注册监听,同时开启监控线程,线程安全 * @param listener */ public void registMonitor(MonitorListener listener){ synchronized (monitorLock) { if(monitorListener == null && listener!=null){ startMonitor(); } monitorListener = listener; } } /** * 注销监听,注销后,线程会关闭,线程安全 */ public void unRegistMonitor(){ synchronized (monitorLock) { monitorListener = null; stopMonitor(); } } /** * 屏幕开启调用,如果有回调接口重新启动监控线程 */ public void screenOn(){ synchronized (monitorLock) { if(monitorListener != null){ startMonitor(); } } } /** * 屏幕关闭调用,关闭监控线程 */ public void screenOff(){ synchronized (monitorLock) { if(monitorListener != null){ stopMonitor(); } } } private void callBackListener(int pattern,String packageName){ synchronized (monitorLock) { if(monitorListener != null){ if(pattern == MONITOR_PATTERN_LOGCAT && monitorPattern == MONITOR_PATTERN_BOATH){ return; } monitorListener.onScreen(packageName); } } } private void startMonitor(){ stopMonitor(); synchronized (monitorLock) { if(monitorPattern == MONITOR_PATTERN_LOGCAT){ logCatThread = new LogCatThread(); logCatThread.start(); }else if(monitorPattern == MONITOR_PATTERN_TIMER){ this.mHandler.sendEmptyMessageDelayed(MSG_LOOP, 1000l); }else if(monitorPattern == MONITOR_PATTERN_BOATH){ timeCount = 0; logCatThread = new LogCatThread(); logCatThread.start(); this.mHandler.sendEmptyMessageDelayed(MSG_LOOP, 1000l); } } } private void stopMonitor(){ if(logCatThread!=null){ logCatThread.destory(); logCatThread = null; } mHandler.removeCallbacksAndMessages(null); } /** * 屏幕监控回调接口 * @author sandrocheng * */ public static interface MonitorListener{ /** * 屏幕当前显示的应用包名 * @param packageName */ public void onScreen(String packageName); } /** * 监听log的线程 * @author sandrocheng * */ private class LogCatThread extends Thread{ private final Pattern actPat = Pattern.compile("act=([^ ]+)"); private final Pattern cmpPat = Pattern.compile("cmp=([^} ]+)"); private final static int TIME_LENGTH = 18; private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private static final String LOG_PATTERN = "logcat -v time ActivityManager:I WindowManager:I *:S"; private Object bufferLock = new Object(); private BufferedReader bufferedReader; private InputStreamReader inputStreamReader; private Process process; private LogCatThread(){ super("LogCatThread"); } @Override public synchronized void start() { super.start(); } private void destory() { synchronized (bufferLock) { if (process != null) { process.destroy(); process = null; } if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException e) { } inputStreamReader = null; } if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { } bufferedReader = null; } } } @Override public void run(){ try { Log.d("WindowMonitor", "LogCatThread start "); process = Runtime.getRuntime().exec(LOG_PATTERN); inputStreamReader = new InputStreamReader(process.getInputStream()); bufferedReader = new BufferedReader(inputStreamReader); String line = ""; Matcher actMatcher = null; Matcher cmpMatcher = null; while (bufferedReader != null) { line = bufferedReader.readLine(); if (line == null) { Log.w("WindowMonitor", "LogCatThread.run bufferedReader.readLine() "); break; } actMatcher = actPat.matcher(line); cmpMatcher = cmpPat.matcher(line); if (actMatcher.find() && cmpMatcher.find()) { handleLog(line, cmpMatcher.group()); } } } catch (IOException e) { Log.w("WindowMonitor", "LogCatThread.run IOException : " + e.toString()); }finally{ destory(); } Log.d("WindowMonitor", "LogCatThread stop "); } private void handleLog(String line, String packageStr) { String timeStr = Calendar.getInstance().get(Calendar.YEAR) + "-" + line.substring(0, TIME_LENGTH); Date date; try { date = simpleDateFormat.parse(timeStr); } catch (ParseException e) { Log.e("WindowMonitor", "handleLog ParseException : " + e.toString()); return; } Calendar dateCalHigh = Calendar.getInstance(); dateCalHigh.setTime(date); dateCalHigh.add(Calendar.SECOND, 5); if(dateCalHigh.after(Calendar.getInstance())){ String packageName = getPackageName(packageStr); callBackListener(MONITOR_PATTERN_LOGCAT,packageName); Log.i("WindowMonitor", "handleLog packageName : " + packageName); monitorPattern = MONITOR_PATTERN_LOGCAT; mHandler.removeCallbacksAndMessages(null); } } private String getPackageName(String packageStr){ String str = packageStr.replace("cmp=", ""); String s = "/."; int index = str.indexOf(s); if(index>0){ return str.substring(0, index); } return ""; } } }