37 votes

Widget pour allumer / éteindre la lampe de poche de la caméra dans Android

Je suis en train d'élaborer un widget pour activer/désactiver la caméra led de téléphone.

J'ai fait un widget qui peut fonctionner comme le bouton à bascule (on/off).

Le comportement est comme suit : Parfois, le voyant reste allumé quand je activer le widget. Mais elle n'est pas allumer/éteindre la caméra led mais il change l'icône.

Je ne suis pas en mesure de comprendre quel est le problème réel.

La même chose fonctionne bien en Activité (lampe de poche à la Demande).

Quelqu'un peut-il svp m'expliquer comment puis-je résoudre mon problème ?

Où je vais mal ?

Vous pouvez regarder le code ci-dessous que j'ai fait jusqu'à présent

onUpdate méthode

@Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

         //super.onUpdate(context, appWidgetManager, appWidgetIds);

        remoteViews = new RemoteViews( context.getPackageName(), R.layout.widgetlayout);
        watchWidget = new ComponentName( context, FlashLightWidget.class );

        Intent intentClick = new Intent(context,FlashLightWidget.class);
        intentClick.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, ""+appWidgetIds[0]);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetIds[0],intentClick, 0);
        remoteViews.setOnClickPendingIntent(R.id.myToggleWidget, pendingIntent);
        appWidgetManager.updateAppWidget( watchWidget, remoteViews );
        ctx=context;      
    }

onReceive méthode est comme suit :

@Override

    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        remoteViews = new RemoteViews( context.getPackageName(), R.layout.widgetlayout);
        if (intent.getAction()==null) {
            Bundle extras = intent.getExtras();
            if(extras!=null) {
                 if(status)
                    {
                        status=false;
                        remoteViews.setImageViewResource(R.id.myToggleWidget, R.drawable.shutdown1);
                        processOnClick();
                        Toast.makeText(context,"Status==false-onclick",Toast.LENGTH_SHORT).show();
                    }
                    else
                    {
                        status = true;
                        remoteViews.setImageViewResource(R.id.myToggleWidget, R.drawable.shutdown2);
                        processOffClick();
                        Toast.makeText(context,"Status==true--Ofclick",Toast.LENGTH_SHORT).show();
                    }
                }

                watchWidget = new ComponentName( context, FlashLightWidget.class );

                (AppWidgetManager.getInstance(context)).updateAppWidget( watchWidget, remoteViews );
           }
        }
  }

processOffClick méthode

private void processOffClick() {

        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();      
            mCamera = null;
        }
    }

processOnClick méthode

private void processOnClick() {

    if(mCamera==null)
    {
        try {
            mCamera = Camera.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    if (mCamera != null) {

        Parameters params = mCamera.getParameters();
        List<String> flashModes = params.getSupportedFlashModes();

        if (flashModes == null) {
            return;
        } else {

                params.setFlashMode(Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(params);
                mCamera.startPreview();

            String flashMode = params.getFlashMode();

            if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {

                if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
                    params.setFlashMode(Parameters.FLASH_MODE_TORCH);
                    mCamera.setParameters(params);

                } 

            }
        }
    } else if (mCamera == null) {
        //Toast.makeText(ctx, "Camera not found", Toast.LENGTH_LONG).show();
        return;
    }
}

40voto

Kartik Points 12151

Après un long moment, je suis libre pour résoudre ce problème.

Voici ce que j'ai fait.

FlashlightWidgetProvider classe :

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

        }
}

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

L'autorisation requise en Manifest.xml le fichier :

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

Enregistrer également les récepteurs Manifest.xml le fichier :

<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>

Remarque importante : Ce code fonctionne parfaitement si votre téléphone dispose d' FLASH_MODE_TORCH pris en charge.

Je l'ai testé dans Samsung Galaxy Ace 2.2.1 & 2.3.3. Le code ne fonctionne pas parce que l'appareil n'a aucune FLASH_MODE_TORCH.

Fonctionne très bien dans HTC Salsa, feu de forêt..

Si quelqu'un peut tester et de publier les résultats ici, ce serait mieux.

6voto

escape-llc Points 755

La meilleure technique de traitement des clics à partir d'un RemoteViews est de créer un PendingIntent que les appels de service et d'exécuter les "trucs" que vous voulez dans le service, y compris les additionnels RemoteViews mises à jour pour votre widget. Vous pouvez envoyer les données pertinentes à l'intention des extras. Les appels de service en stopSelf() à la fin, de sorte qu'il s'arrête.

Vous ne pouvez pas maintenir un état, une BroadcastReceiver; le système d'exécution de ces sur le fil, et de ne pas maintenir toute référence à votre instance après l'appel de onReceive(). Votre mCamera variable n'est pas assuré d'être maintenu entre les appels de votre BroadcastReceiver.

Si vous avez vraiment besoin de maintenir un état, vous devez le faire dans le service, et de ne pas utiliser stopSelf() (jusqu'à une heure appropriée).

Vous n'avez pas besoin d'un thread d'INTERFACE utilisateur à utiliser l' Camera classe, sauf si vous faites de prévisualisation de l'image, ce qui nécessite un SurfaceHolder (et implique une interface utilisateur (IU). Vous devez, cependant, ont une boucle active, ou Camera de ne pas poster des rappels pour vous, ce qui est un problème depuis Camera est essentiellement asynchrone. Vous pouvez le faire au sein d'un service (voir HandlerThread) et de garder votre service en cours d'exécution jusqu'à ce qu'il est temps d' release() tout. Selon ce thread appelle Camera.open() recevrez des rappels.

Tout le monde n'a réellement lu l'article sur l'App Widgets? http://developer.android.com/guide/topics/appwidgets/index.html

À l'aide de la AppWidgetProvider de la Classe de la section dit à peu près ce que je dis ici.

2voto

Yossi Points 621

J'ai eu une situation similaire où je dois exécuter un certain code Android sur le thread d'interface utilisateur ... qui n'est disponible que dans une activité. Ma solution - une activité avec une mise en page complètement transparente. Vous ne voyez donc que votre écran d'accueil (bien qu'il ne réponde pas) pendant que vous terminez vos actions, ce qui dans votre cas devrait être assez rapide.

1voto

Mauricio Points 98

J'ai une solution qui n'est pas géniale mais qui fonctionne. Demandez au widget d'appeler une activité et, dans l'activité, activez le flash, puis fermez l'activité. La même chose pour l'éteindre. Si cela fonctionne dans l'activité, cette solution fonctionnera. Ce n'est pas élégant mais ça marche. Je l'ai essayé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X