package com.hellodev.lightme; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.media.AudioManager; import android.media.SoundPool; import android.media.SoundPool.OnLoadCompleteListener; import android.util.Log; import com.hellodev.lightme.service.ServiceHelper; import com.hellodev.lightme.util.MLisenseMangaer; import com.hellodev.lightme.util.MPreferenceManager; import java.util.ArrayList; import java.util.List; public class FlashController { private final static String TAG = "FlashController"; private static FlashController mInstance; public final static int LEVEL_MAX = 7; public final static int LEVEL_OFF = 0; private int currentLevel; private Parameters parameters; private Camera camera; private int switchSound; private SoundPool soundPool; private boolean isSoundInit;// 是否可以播放 private boolean enableSound;// 是否可以开声音 private long AUTO_CLOSE_TIME_INTERVAL = 0; private AlarmManager alarmManager;// FIXME这个可以Softreference private PendingIntent autoCloseRequest; private long flashOpenTimeMills = 0; private List<OnFlashLevelChangedListener> observers; private int lisenseState = -1; private boolean lisenseEnable; private FlashHelper flashHelper; private Object CAMERA_LOCK = new Object(); private boolean isCameraInited = false; // FIXME 执行完毕之后是否需要显式去停止 private Runnable cameraInitTask = new Runnable() { @Override public void run() { initCamera(hasCameraReleased()); } }; private FlashController() { lisenseEnable = true; currentLevel = LEVEL_OFF; flashHelper = new FlashHelper(); enableSound = MPreferenceManager.getInstance().isSwitchSoundOn(); } public static FlashController getInstance() { if (mInstance == null) mInstance = new FlashController(); return mInstance; } // FIXME 在哪释放 public void releaseInstance() { if (mInstance != null) { relaseSwitchSound(); releaseAutoCloseMgr(); releaseCamera(); mInstance = null; observers.removeAll(observers); } } // FIXME 线程执行完毕之后需不需要停止 public void initCameraSync() { Thread cameraInitThread = new Thread(cameraInitTask); cameraInitThread.start(); } /* * 回到桌面的时候需要调用一次 */ public void initCamera() { initCamera(hasCameraReleased()); } private void initCamera(boolean needReconnect) { synchronized (CAMERA_LOCK) { if(isCameraInited == false) { if (needReconnect && camera != null) { camera = null; } try { if (camera == null) camera = Camera.open(); parameters = camera.getParameters(); } catch (RuntimeException re) { parameters = null; } if (needReconnect && currentLevel > LEVEL_OFF) { currentLevel = LEVEL_OFF; notifyFlashLevelChanged();//重新打开需要通知对应的观察者 turnFlashOffIfCameraReleased(); } isCameraInited = parameters != null; } } } /* * 关灯灭屏时释放Camera,亮屏幕时不着急调用,首次调用时打开 */ public void releaseCamera() { synchronized (CAMERA_LOCK) { if (camera != null) { try { camera.release(); } catch (RuntimeException re) { Log.v(TAG, "camera already released"); } camera = null; isCameraInited = false; } } } public void initSwitchSound() { if (enableSound && (isSoundInit == false || soundPool == null)) { soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); soundPool.setOnLoadCompleteListener(soundInitListener); switchSound = soundPool.load(FlashApp.getContext(), R.raw.flashswitch, 1); } } OnLoadCompleteListener soundInitListener = new OnLoadCompleteListener() { @Override public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { isSoundInit = true; } }; /* * 关灯灭屏时释放,亮屏幕时不着急调用,首次调用时打开 */ public void relaseSwitchSound() { if (soundPool != null && isSoundInit) { soundPool.release(); soundPool = null; isSoundInit = false; } } public void enableSound() { enableSound = true; initSwitchSound();// 打开这个时,用户应该很快想去试试,所以提前加载 } public void disabelSound() { enableSound = false; relaseSwitchSound(); } // FIXME 这样还是不能确保,可能那一次没有声音 public void playSwitchSound() { initSwitchSound(); if (enableSound && isSoundInit) soundPool.play(switchSound, 1.5f, 1.5f, 0, 0, 1); } private void initAutoCloseMgr() { if (alarmManager == null) { alarmManager = (AlarmManager) FlashApp.getContext() .getSystemService(Context.ALARM_SERVICE); } } public void releaseAutoCloseMgr() { cancelAutoCloseTask(); alarmManager = null; autoCloseRequest = null; } /* * 调用时机 1. 开灯的时候 2. 调整设置项的时候 FIXME 如果时间已经过了 */ private void requestAutoCloseTask() { requestAutoCloseTask(0); } public void requestAutoCloseTask(long autoCloseTimInterval) { initAutoCloseMgr(); if(autoCloseTimInterval > 0) { AUTO_CLOSE_TIME_INTERVAL = autoCloseTimInterval; } else if(AUTO_CLOSE_TIME_INTERVAL == 0) { AUTO_CLOSE_TIME_INTERVAL = MPreferenceManager.getInstance().getAutoCloseTime() * 60000; } if (currentLevel > LEVEL_OFF) { long triggleAtMills = flashOpenTimeMills + AUTO_CLOSE_TIME_INTERVAL; Intent requestIntent = ServiceHelper.getAutoCloseIntent(); autoCloseRequest = PendingIntent.getService(FlashApp.getContext(), 0, requestIntent, PendingIntent.FLAG_CANCEL_CURRENT); alarmManager .set(AlarmManager.RTC, triggleAtMills, autoCloseRequest); } } public void cancelAutoCloseTask() { if (autoCloseRequest != null) { alarmManager.cancel(autoCloseRequest); autoCloseRequest = null; } } public int toggleFlash() { initCamera(); if (currentLevel == LEVEL_OFF) { turnFlashOn(); } else { turnFlashOff(); } return currentLevel; } private void turnFlashOn() { if (isCameraInited && currentLevel == LEVEL_OFF) { parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); try { camera.setParameters(parameters); } catch (RuntimeException re) { initCamera(true); parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); } currentLevel = LEVEL_MAX; flashOpenTimeMills = System.currentTimeMillis(); requestAutoCloseTask(); playSwitchSound(); } } public void turnFlashOff() { if (isCameraInited && currentLevel > LEVEL_OFF) { parameters.setFlashMode(Parameters.FLASH_MODE_OFF); try { camera.setParameters(parameters); } catch (RuntimeException re) { initCamera(true); parameters.setFlashMode(Parameters.FLASH_MODE_OFF); } currentLevel = LEVEL_OFF; flashOpenTimeMills = 0; cancelAutoCloseTask(); playSwitchSound(); } } public void turnFlashOffIfCameraReleased() { if(currentLevel > LEVEL_OFF) { currentLevel = LEVEL_OFF; flashOpenTimeMills = 0; cancelAutoCloseTask(); } } /* * 调节亮度需要lisenseEnable才可以 */ public int turnFlashUp() { if (lisenseEnable && currentLevel < LEVEL_MAX) { flashHelper.changeFlashLight(true); currentLevel++; } return currentLevel; } public int turnFlashDown() { if (lisenseEnable && currentLevel > LEVEL_OFF + 1) { flashHelper.changeFlashLight(false); currentLevel--; } return currentLevel; } public boolean hasCameraReleased() { boolean hasReleased = false; if(camera == null) { hasReleased = true; isCameraInited = false; } else { try { parameters = camera.getParameters(); } catch (RuntimeException re) { hasReleased = true; isCameraInited = false; } } return hasReleased; } public int getCurrentLevel() { return currentLevel; } public boolean isFlashOn() { return currentLevel > LEVEL_OFF; } public void notifyFlashLevelChanged() { if (observers != null) { for (OnFlashLevelChangedListener observer : observers) { observer.onFlashLevelChanged(currentLevel); } } } public void setLisenseState(int lisenseState) { if (this.lisenseState != lisenseState) { this.lisenseState = lisenseState; lisenseEnable = lisenseState == MLisenseMangaer.STATE_PURCHASED || lisenseState == MLisenseMangaer.STATE_TRYING; if(!lisenseEnable) { //关闭对应设置项,并通知更新 MPreferenceManager prefsMgr = MPreferenceManager.getInstance(); prefsMgr.toggleKeyguardPanel(false, true); prefsMgr.toggleLauncherPanel(false, true); //FIXME preference的写入考虑使用队列的形式 } } } public int getLisenseState() { return lisenseState; } public boolean islisenseEnable() { return lisenseEnable; } public boolean isPurchased() { return lisenseState == MLisenseMangaer.STATE_PURCHASED; } public void addObserver(OnFlashLevelChangedListener listener) { if (observers == null) observers = new ArrayList<OnFlashLevelChangedListener>(); if (!observers.contains(listener)) { observers.add(listener); } } public void removeObserver(OnFlashLevelChangedListener listener) { if (observers != null && observers.contains(listener)) { observers.remove(listener); } } public interface OnFlashLevelChangedListener { public void onFlashLevelChanged(int currentLevel); } }