8.【小萌伴Android】手電筒功能及其實現
前面三篇介紹了【小萌伴】百寶箱中的三款原生小 遊 戲,這裡說說百寶箱中另一功能模組--實用小應用...

【小萌伴】手電筒.gif
小應用主要包含了四個功能:今日曆史、新聞、手電筒和找手機;今日曆史和新聞模組之前已經介紹過(參考: 3.【小萌伴Android】新聞/H5遊戲模組及廣告過濾 ),本篇只介紹手電筒功能及其實現,後續再聊找手機功能。
原理
手電筒功能其實是利用手機照相機的閃光燈(LED發光二極體),這個元件最初是用於手機在黑暗環境下拍照使用的,後來利用它發光的特性,做了手機手電筒功能(這裡提示,手電筒功能其實也是對閃關燈的一種損壞,雖然LED燈壽命比較長,但是長時間持續使用有損該元件,建議只在應急情況下使用,特別是在手機發熱嚴重時請停止使用)。

【小萌伴】手電筒.jpg
實現
在支援閃光燈的手機中,我們可以利用Camera類檢測並開啟閃光燈:
/** * 是否支援手電筒功能 * @param context * @return */ public static boolean hasFlash(Context context) { PackageManager pm = context.getPackageManager(); FeatureInfo[] featureInfos = pm.getSystemAvailableFeatures(); for (FeatureInfo f : featureInfos) { if (PackageManager.FEATURE_CAMERA_FLASH.equals(f.name)) { return true; } } return false; }
獲取Camera實體,這裡先使用open類,有的手機需要指定cameraId:
public static Camera getCamera(Context context) { if (!hasFlash(context)) return null; if (sCamera == null) { try { sCamera = Camera.open(); } catch (Exception e) { try { sCamera = Camera.open(Camera.getNumberOfCameras() - 1); } catch (Exception e1) { TastyToastUtil.toast(E7App.mApp, R.string.flashlight_open_error); } } } return sCamera; }
開啟與關閉閃光燈
private static void ensureCamera(Context context) { getCamera(context); } public static void openFlash(Context context) { ensureCamera(context); if (sCamera == null) return; try { Camera.Parameters parameters = sCamera.getParameters(); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); sCamera.setParameters(parameters); sCamera.cancelAutoFocus(); sCamera.startPreview(); } catch (Exception e) { } } public static void closeFlash() { if (sCamera == null) return; try { Camera.Parameters parameters = sCamera.getParameters(); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); sCamera.setParameters(parameters); } catch (Exception e) { } }
通知及廣播
在開啟閃光燈後,可能我們退出了應用,這時候想要關閉閃光燈還得重新進入應用,比較麻煩,所以通過傳送一個通知欄訊息,點選通知即可關閉閃光燈:
public class NotificationControl { public static final int sNotificationId = 318; public static void showNotification(Context context) { NotificationCompat.Builder builder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_notify) .setContentTitle(context.getString(R.string.app_name)) .setContentText(context.getString(R.string.notification_text)); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(FlashLightWidget.ACTION_LED_OFF), 0); builder.setContentIntent(pendingIntent); NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(sNotificationId, builder.build()); } public static void cancelNotification(Context context) { NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); manager.cancel(sNotificationId); } }
這裡還定義了一個廣播接收:
BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (FlashLightWidget.ACTION_LED_ON.equals(intent.getAction())) { flashOpend(); } else if (FlashLightWidget.ACTION_LED_OFF.equals(intent.getAction())) { flashClosed(); } } };

【小萌伴】手電筒2.jpg
小元件
為了方便使用,手電筒功能添加了桌面小元件FlashLightWidget,繼承AppWidgetProvider,在onReceive中處理ACTION_LED_ON和ACTION_LED_OFF並且在onUpdate進行更新:(onReceive程式碼比較多就不放出來了)
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // There may be multiple widgets active, so update all of them for (int widgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, widgetId); } } static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) { RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.flash_light_widget); views.setImageViewResource(R.id.widget_led, R.drawable.widget_led); views.setInt(R.id.widget_led, "setBackgroundResource", R.drawable.widget_led_bg); views.setOnClickPendingIntent(R.id.widget_led, PendingIntent.getBroadcast(context, 0, new Intent(ACTION_LED_ON), 0)); appWidgetManager.updateAppWidget(appWidgetId, views); }
這樣,就可以將小元件拖到桌面,點選桌面圖示就可以控制手電筒的開關了。

IT老五(it-lao5):關注公眾號,一起源創,一起學習!