Search code examples
androidcameraandroid-widgetwidgetandroid-appwidget

Flashlight widget does not turn off


I have created everything necessary for my widget to exist and function. Even so at the first click, t does what it is supposed to but then image gets changed and says problem, and does not function. I want it to open flash and then close it. Help will be much appreciated.

FlashlightWidgetProvider

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.flash_widget);
               views.setOnClickPendingIntent(R.id.button, pendingIntent);

               appWidgetManager.updateAppWidget(appWidgetIds, views);

       }
}

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.flash_widget);

                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();
                                }
                        }
                }
        }
}

Solution

  • Make sure the button resource refers to an ImageView and not a regular Button. I just tried this out at first with a Button in my layout file and I was getting the same problem where the widget would basically crash and remove itself from the home screen. When I changed button to be an ImageView in the layout file, the code now works.

    I did modify the code a bit from yours, so in case that doesn't work by itself, here is the updated FlashlightWidgetProvider:

    public class FlashlightWidgetProvider extends AppWidgetProvider {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction())) {
                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getClass()));
    
                Intent broadcastIntent = new Intent(context, FlashlightWidgetReceiver.class);
                broadcastIntent.setAction("COM_FLASHLIGHT");
                broadcastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
                PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                                                                         0,
                                                                         broadcastIntent,
                                                                         PendingIntent.FLAG_UPDATE_CURRENT);
    
                RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.flashlight);
                views.setOnClickPendingIntent(R.id.flashButton, pendingIntent);
    
                appWidgetManager.updateAppWidget(appWidgetIds, views);
            }
    
            super.onReceive(context, intent);
        }
    }
    

    Also, make sure to register the widget provider and receiver correctly in the manifest (replacing the relevant pieces with your own, of course):

        <receiver
            android:name="com.example.stackoverflowtester.widget.FlashlightWidgetProvider"
            android:label="Flashlight" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
    
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/flashlight_widget_provider" />
        </receiver>
        <receiver android:name="com.example.stackoverflowtester.widget.FlashlightWidgetReceiver" >
            <intent-filter>
                <action android:name="COM_FLASHLIGHT" />
            </intent-filter>
        </receiver>