package com.hellodev.lightme.service; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import com.hellodev.lightme.FlashApp; import com.hellodev.lightme.FlashController; import com.hellodev.lightme.receiver.SystemReceiver; import com.hellodev.lightme.util.MLisenseMangaer; import com.hellodev.lightme.util.MNotificationHelper; import com.hellodev.lightme.util.MPreferenceManager; import com.hellodev.lightme.util.ShakeDetector; import com.hellodev.lightme.util.MLisenseMangaer.OnLisenseStateChangeListener; import com.hellodev.lightme.util.ShakeDetector.OnShakeListener; import com.hellodev.lightme.view.KeyguardPanelManager; import com.hellodev.lightme.view.LauncherPanelManager; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.KeyguardManager; import android.app.Notification; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.IBinder; import android.os.Vibrator; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; public class PanelService extends Service implements OnShakeListener, OnLisenseStateChangeListener { private final static String TAG = "ControlService"; public static final String CONTROL_TYPE_KEY = "control_type"; public static final int CONTROL_TYPE_DEFAULT = 0; public static final int CONTROL_TYPE_START = 1; public static final int CONTROL_TYPE_STOP = 2; public static final int CONTROL_TYPE_SCREEN_OFF = 3; public static final int CONTROL_TYPE_SCREEN_ON = 4; public static final int CONTROL_TYPE_USER_PRESENT = 5; public final static String ACTION_LAUNCHER = "hellodev.service.action.LAUNCHER"; public final static String ACTION_KEYGUARD = "hellodev.service.action.KEYGUARD"; public final static String ACTION_PANEL_SERVICE = "hellodev.service.action.PANEL_SERVICE"; private LauncherPanelManager mLauncherPanelManager; private KeyguardPanelManager mKeyguardPanelManager; private FlashController flashController; private MLisenseMangaer lisenseManager; private Timer mLauncherRefreshTimer; private LauncherRefreshTask mLauncherRefreshTask; private MPreferenceManager mPrefsManager; private MNotificationHelper notifyHelper; private ActivityManager mActivityManager; private Vibrator mVibrator; private SystemReceiver mSystemReceiver; private ShakeDetector mShakeDetector; private TelephonyManager mTelephonyManager; private PhoneStateListener mPhoneStateListener; private KeyguardManager mKeyguardManager; private Handler mHandler = new Handler(); private boolean isKeyguardServiceAlive, isLauncherServiceAlive; @Override public void onCreate() { super.onCreate(); Context appContext = FlashApp.getContext(); flashController = FlashController.getInstance(); mPrefsManager = MPreferenceManager.getInstance(); mActivityManager = (ActivityManager) appContext .getSystemService(Context.ACTIVITY_SERVICE); mVibrator = (Vibrator) appContext .getSystemService(Context.VIBRATOR_SERVICE); isKeyguardServiceAlive = isLauncherServiceAlive = false; mLauncherRefreshTimer = new Timer(); mShakeDetector = new ShakeDetector(appContext); mShakeDetector.registerOnShakeListener(this); mKeyguardManager = (KeyguardManager) appContext .getSystemService(Context.KEYGUARD_SERVICE); notifyHelper = new MNotificationHelper(); //这个只在锁屏界面才需要监听 mPhoneStateListener = new PhoneStateListener() { int lastState = TelephonyManager.CALL_STATE_IDLE; @Override public void onCallStateChanged(int state, String incomingNumber) { if(state != lastState && isKeyguardServiceAlive) { if(state == TelephonyManager.CALL_STATE_IDLE) { mKeyguardPanelManager.showPanel(); if (mPrefsManager.isKeyguardShockEnable()) mShakeDetector.start();//FIXME需要测试 } else if(state == TelephonyManager.CALL_STATE_RINGING) { mKeyguardPanelManager.hidePanel(); if (mPrefsManager.isKeyguardShockEnable()) mShakeDetector.stop(); } } lastState = state; super.onCallStateChanged(state, incomingNumber); } }; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); int controlType = intent.getIntExtra(CONTROL_TYPE_KEY, CONTROL_TYPE_DEFAULT); if (CONTROL_TYPE_START == controlType) handleStart(action); else if (CONTROL_TYPE_STOP == controlType) handleStop(action); else if (controlType == CONTROL_TYPE_SCREEN_ON) handleScreenOn(); else if (controlType == CONTROL_TYPE_SCREEN_OFF) handleScreenOff(); else if (controlType == CONTROL_TYPE_USER_PRESENT) handleUserPresent(); } else { Log.v(TAG, "onStartCommand() restart after kill"); handleStart(ACTION_PANEL_SERVICE); } return START_STICKY; } @Override public void onDestroy() { releaseData(); super.onDestroy(); } private void releaseData() { //FIXME 只有调用stop才会执行这一步,unregister放在这里 if (mSystemReceiver != null) FlashApp.getContext().unregisterReceiver(mSystemReceiver); mSystemReceiver = null; flashController = null; mActivityManager = null; mVibrator = null; mPrefsManager = null; if(mShakeDetector != null) { mShakeDetector.removeOnShakeListener(this); } //关闭监听 if(mTelephonyManager != null) { mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_NONE); } } @Override public IBinder onBind(Intent intent) { return null; } /* * 调用时机 1. 重启的时候:BootComplete 2. 设置:SettingActivity * * * 需要根据preference值,因为可能是重启时的调用 */ private void handleStart(String action) { if (!isLauncherServiceAlive && !isKeyguardServiceAlive) { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); mSystemReceiver = new SystemReceiver(); FlashApp.getContext().registerReceiver(mSystemReceiver, filter); } if (ACTION_LAUNCHER.equals(action)) startLauncherPanel(); else if (ACTION_KEYGUARD.equals(action)) startKeyguardPanel(); else { if (mPrefsManager.isLauncherPanelShown()) startLauncherPanel(); if (mPrefsManager.isKeyguardPanelShown()) startKeyguardPanel(); } } /* * 调用时机 1. 设置 * 覆盖安装之后service没有起来,没有执行过start,这个时候不能执行unregisterReceiver */ private void handleStop(String action) { if (ACTION_LAUNCHER.equals(action)) stopLauncherPanel(); else if (ACTION_KEYGUARD.equals(action)) stopKeyguardPanel(); else { // 暂时未使用 stopLauncherPanel(); stopKeyguardPanel(); } if (!isLauncherServiceAlive && !isKeyguardServiceAlive) { stopSelf(); } } /* * 调用时机: 1. 屏幕点亮的时候:(仍然处在锁屏幕) 2. 呼吸灯上滑解锁的时候:(发生在user_present之后) * * 不在锁屏都关闭:电话的时候判断状态 * 如果在锁屏界面则打开锁屏panel * 如果lisense过期,关闭Keyguard * * 如果在锁屏界面才监听电话 */ private void handleScreenOn() { // initLisense(); //FIXME 需要优化的策略,原则1. 尽量节省资源 2. 不要影响效果 if(!flashController.isFlashOn()) { flashController.initCameraSync(); } else { if(flashController.hasCameraReleased()) { flashController.turnFlashOffIfCameraReleased(); flashController.initCameraSync(); } } if (!isKeyguardScreen()) { if (isKeyguardServiceAlive) mKeyguardPanelManager.hidePanel(); } else { if (isKeyguardServiceAlive) { if(isTelephoneCalling()) { mKeyguardPanelManager.hidePanel(); } else { mKeyguardPanelManager.showPanel();//灭屏、亮屏都show mKeyguardPanelManager.updatePanelWhenVisiable(); if (mPrefsManager.isKeyguardShockEnable()) { mShakeDetector.start(); } } //锁屏界面需要监听电话状态 mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_CALL_STATE); } } } /* * 调用时机: 1. 灭屏的时候 2. 通话的时候会导致灭屏幕 * * * 灭屏幕的时候是否会被杀掉,杀掉之后的处理方式 */ private void handleScreenOff() { if (isLauncherServiceAlive && !isTelephoneCalling()) { mLauncherRefreshTask.cancelSelf(); hideLauncherPanel(); } if (isKeyguardServiceAlive) { mShakeDetector.stop(); if (!isTelephoneCalling()) mKeyguardPanelManager.showPanel(); //关闭监听 if(mTelephonyManager != null) { mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_NONE); } } //FIXME 需要优化的策略 if(!flashController.isFlashOn()) { flashController.releaseCamera(); } else { //如果是亮着的需要判断一下相机是否已经被占用 if(flashController.hasCameraReleased()) { flashController.turnFlashOffIfCameraReleased(); } } } /* * 调用时机: 1. 解锁的时候:先screen_on再user_present 2. * 直接滑动呼吸灯解锁:先user_present再screen_on * * * 覆盖安装会kill掉process,不会调用onDestroy,service也不会自动重启 */ private void handleUserPresent() { if (isKeyguardServiceAlive) { mKeyguardPanelManager.hidePanel(); if (mPrefsManager.isKeyguardShockEnable()) mShakeDetector.stop(); //关闭监听 if(mTelephonyManager != null) { mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_NONE); } } if(isLauncherServiceAlive) startLauncherRefreshTask(0, 1000); } private void startLauncherPanel() { if (!isLauncherServiceAlive) { isLauncherServiceAlive = true; if (mLauncherPanelManager == null) mLauncherPanelManager = new LauncherPanelManager(); if (!isKeyguardScreen()) { // 如果覆盖安装了,这个时候启动LauncherPanel不应该开始轮询,而应该等到user_present的时候 startLauncherRefreshTask(0, 1000); } else { //如果覆盖安装的地方在锁屏,如果不初始化则无法进行后续处理 mLauncherRefreshTask = new LauncherRefreshTask(); } //FIXME //startLauncherRefreshTask(0, 1000);//因为有密码的时候可能需要进入其他界面,这个时候也应该轮询 //foreground startForeground(1000, new Notification()); } } private void stopLauncherPanel() { if (isLauncherServiceAlive) { isLauncherServiceAlive = false; mLauncherRefreshTask.cancelSelf(); // closePanel mLauncherPanelManager.closePanel(); // stopService //FIXME 这样会导致只打开锁屏的时候会有一段时间关闭锁屏开关 stopForeground(true); notifyHelper.cancelNotify(MNotificationHelper.NOTIFICATION_TYPE_LAUCHER_PANEL); } } private void requestShowLauncherPanel() { // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。postRunnable的原因是因为timerTask mHandler.post(new Runnable() { @Override public void run() { if (isLauncherServiceAlive) { showLauncherPanel(); } } }); } // 灭屏幕的时候应该是cancel掉任务,present的时候应该是show那个view,ok了之后启动桌面轮询task private void requestHideLauncherPanel() { // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。 mHandler.post(new Runnable() { @Override public void run() { if (isLauncherServiceAlive) { hideLauncherPanel(); } } }); } private void showLauncherPanel() { if(flashController.hasCameraReleased()) { flashController.turnFlashOffIfCameraReleased(); flashController.initCameraSync(); } mLauncherPanelManager.showPanel(); } private void hideLauncherPanel() { mLauncherPanelManager.hidePanel(); } /* * 调用时机: 1. 打开设置项 2. 开机启动的时候 */ private void startKeyguardPanel() { if (isKeyguardServiceAlive == false) { if (mKeyguardPanelManager == null) mKeyguardPanelManager = new KeyguardPanelManager(); isKeyguardServiceAlive = true; } } /* * 调用时机 1. 关闭设置项的时候 2.长按移除的时候 */ private void stopKeyguardPanel() { if (isKeyguardServiceAlive) { isKeyguardServiceAlive = false; mKeyguardPanelManager.closePanel(); // //如果是可以摇动的时候 mShakeDetector.stop(); //关闭监听 if(mTelephonyManager != null) { mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_NONE); } notifyHelper.cancelNotify(MNotificationHelper.NOTIFICATION_TYPE_KEYGUARD_PANEL); notifyHelper.cancelNotify(MNotificationHelper.NOTIFICATION_TYPE_KEYGUARD_SHOCK); //如果锁屏插件关闭,关闭监听 if(mTelephonyManager != null) { mTelephonyManager.listen(mPhoneStateListener , PhoneStateListener.LISTEN_NONE); } } } private boolean isHome() { boolean isHome = false; List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1); isHome = getHomes().contains(tasks.get(0).topActivity.getClassName()); return isHome; } private List<String> getHomes() { List<String> names = new ArrayList<String>(); PackageManager packageManager = this.getPackageManager(); Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities( intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo ri : resolveInfo) { names.add(ri.activityInfo.name); } return names; } @Override public void onShake() { mVibrator.vibrate(200); flashController.toggleFlash(); flashController.notifyFlashLevelChanged();//这是一个全局的操作,虽然现在只是keyguard在observer中 } private boolean isTelephoneCalling() { if (mTelephonyManager == null) mTelephonyManager = (TelephonyManager) FlashApp.getContext() .getSystemService(Context.TELEPHONY_SERVICE); boolean calling = false; int status = mTelephonyManager.getCallState(); if (status == TelephonyManager.CALL_STATE_OFFHOOK || status == TelephonyManager.CALL_STATE_RINGING) { calling = true; } return calling; } private boolean isKeyguardScreen() { return mKeyguardManager.isKeyguardLocked(); } //FIXME 这个地方还是有闪动的情况 private void startLauncherRefreshTask(long delay, long period) { boolean isNewTask = true; if(mLauncherRefreshTask == null) { mLauncherRefreshTask = new LauncherRefreshTask(); } else { if(!mLauncherRefreshTask.isRunning()) { mLauncherRefreshTask = new LauncherRefreshTask(); } else { isNewTask = false; } } if(isNewTask) mLauncherRefreshTimer.schedule(mLauncherRefreshTask, delay, period); } private class LauncherRefreshTask extends TimerTask { boolean isLauncherTaskCanceledOrStoped = false; @Override public void run() { if (isLauncherTaskCanceledOrStoped) { requestHideLauncherPanel(); this.cancel(); } else { boolean isHome = isHome(); boolean hasLauncherPanelShown = mLauncherPanelManager.isPanelShown(); if (isHome && hasLauncherPanelShown == false) { if(flashController.hasCameraReleased()) { flashController.turnFlashOffIfCameraReleased(); flashController.initCameraSync(); } requestShowLauncherPanel(); } else if(isHome == false && hasLauncherPanelShown == true) requestHideLauncherPanel(); } } //isCurrent标记当前task是否需要被取代 void cancelSelf() { isLauncherTaskCanceledOrStoped = true; } boolean isRunning() { return !isLauncherTaskCanceledOrStoped; } } private void initLisense() { boolean purchased = flashController.isPurchased(); if(!purchased) { lisenseManager = new MLisenseMangaer(this); lisenseManager.bindRemoteService(); } } //FIXME 现在的逻辑是主界面锁住了,跳转到launcher的panel仍然存在 @Override public void onRemoteServiceConnected() { int lisenseState = lisenseManager.doRemoteCheck(); flashController.setLisenseState(lisenseState); lisenseManager.unbindRemoteService(); if(flashController.islisenseEnable() == false) { handleStop(ACTION_PANEL_SERVICE); notifyHelper.notifyPanelCloseWhenLock(); } } @Override public void onRemoteServiceDisconnected() { lisenseManager = null; } }