Widget for turning on/off camera flashlight in android Widget for turning on/off camera flashlight in android android android

Widget for turning on/off camera flashlight in android


After a long time, I got free to solve this problem.

Here is what I did.

FlashlightWidgetProvider class :

public class FlashlightWidgetProvider extends AppWidgetProvider {        @Override        public void onUpdate(Context context, AppWidgetManager appWidgetManager,                        int[] appWidgetIds) {                Intent receiver = new Intent(context, FlashlightWidgetReceiver.class);                receiver.setAction("COM_FLASHLIGHT");                receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);                PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);                RemoteViews views = new RemoteViews(context.getPackageName(),                                R.layout.widget_layout);                views.setOnClickPendingIntent(R.id.button, pendingIntent);                appWidgetManager.updateAppWidget(appWidgetIds, views);        }}

and BroadcastReceiver for FlashlightWidgetReceiver :

public class FlashlightWidgetReceiver extends BroadcastReceiver {            private static boolean isLightOn = false;            private static Camera camera;            @Override            public void onReceive(Context context, Intent intent) {                    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);                    if(isLightOn) {                            views.setImageViewResource(R.id.button, R.drawable.off);                    } else {                            views.setImageViewResource(R.id.button, R.drawable.on);                    }                    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);                    appWidgetManager.updateAppWidget(new ComponentName(context,     FlashlightWidgetProvider.class),                                                                                     views);                    if (isLightOn) {                            if (camera != null) {                                    camera.stopPreview();                                    camera.release();                                    camera = null;                                    isLightOn = false;                            }                    } else {                            // Open the default i.e. the first rear facing camera.                            camera = Camera.open();                            if(camera == null) {                                    Toast.makeText(context, R.string.no_camera, Toast.LENGTH_SHORT).show();                            } else {                                    // Set the torch flash mode                                    Parameters param = camera.getParameters();                                    param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);                                    try {                                            camera.setParameters(param);                                            camera.startPreview();                                            isLightOn = true;                                    } catch (Exception e) {                                            Toast.makeText(context, R.string.no_flash, Toast.LENGTH_SHORT).show();                                    }                            }                    }            }    }

Permission required in Manifest.xml file :

<uses-permission android:name="android.permission.CAMERA"></uses-permission>

Also register receivers in Manifest.xml file :

<receiver android:name=".FlashlightWidgetProvider" android:icon="@drawable/on" android:label="@string/app_name">         <intent-filter>            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />         </intent-filter>         <meta-data android:name="android.appwidget.provider"                        android:resource="@xml/flashlight_appwidget_info" /></receiver><receiver android:name="FlashlightWidgetReceiver">        <intent-filter>               <action android:name="COM_FLASHLIGHT"></action>        </intent-filter> </receiver>

Important Note : This code works perfect if your phone has FLASH_MODE_TORCH supported.

I have tested in Samsung Galaxy Ace 2.2.1 & 2.3.3. The code is not working because that device has no FLASH_MODE_TORCH.

Works fine in HTC Salsa, Wildfire..

If anyone can test and post results here, it would be best.


The best technique for handling clicks from a RemoteViews is to create a PendingIntent that calls a service, and perform the "stuff" you want in the service, including any additional RemoteViews updates for your widget. You can send along the relevant data in the intent extras. The service calls stopSelf() at the end, so it shuts off.

You cannot maintain any state in an BroadcastReceiver; the system runs those on any available thread, and doesn't maintain any reference to your instance after calling onReceive(). Your mCamera variable is not guaranteed to be maintained between invocations of your BroadcastReceiver.

If you really need to maintain state, you must do it in the service, and don't use stopSelf() (until an appropriate time).

You do not need a UI thread to use the Camera class, unless you are doing image preview, which requires a SurfaceHolder (and implies a UI). You must, however, have an event loop active, or Camera will not post callbacks to you, which is a problem since Camera is primarily asynchronous. You can do this within a service (see HandlerThread) and keep your service running until it's time to release() everything. Whichever thread calls Camera.open() will receive callbacks.

Did everyone actually read the section on App Widgets?http://developer.android.com/guide/topics/appwidgets/index.html

Using the AppWidgetProvider Class section says pretty much what I am saying here.


I had a similar situation where I need to run certain android code on the UI thread ... which is only available in an Activity. My solution - an activity with a completely transparent layout. So you just see your home screen (albeit unresponsive) while you complete your actions, which in your case should be pretty quick.