Widget para encender/apagar la linterna cámara en android

Estoy desarrollando un widget para encender/apagar la cámara led de teléfono.

He hecho un widget que puede funcionar como botón de conmutación (on/off).

Comportamiento es como sigue : a Veces la luz del led permanece encendido cuando puedo activar el widget.
Pero no encender/apagar el led de la cámara, pero cambia el icono.

No soy capaz de averiguar cuál es el problema real.

La misma cosa funciona bien en la Actividad (Luz de la linterna de la Aplicación).

Puede alguien por favor me explique cómo puedo resolver mi problema ?

Donde estoy mal ?

Puede buscar en el siguiente código que he hecho hasta ahora

onUpdate método

@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étodo es como sigue :

@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étodo

private void processOffClick() {

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

processOnClick método

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;
    }
}
  • Por favor, consulte este artículo para obtener una solución válida: stackoverflow.com/questions/3878294/…
  • Eso no me ayuda amigo.. tengo refieren muchas veces antes.. Lo que yo estoy pidiendo es totalmente diferente.
  • Si estoy leyendo lo que ustedes están haciendo correctamente… parecen estar tratando de controlar el led de la app widget de proveedor, Es esto correcto? Si lo que usted necesita para tirar de ese código y lo puso en su propia clase y llamar a esa clase de su aplicación widget de proveedor
  • Sí estás en lo correcto. Estoy tratando de controlar el led de la app widget de proveedor. Pero creo que estoy poniendo en práctica las cosas equivocadas en AppWidgetProvider. Manejo de eventos de clic en onReceive método no es adecuado creo !
  • Eso es correcto. El AppWidgetProvider es muy limitado en lo que puede hacer. Acceso el diseño de widgets a través de RemoteViews developer.android.com/reference/android/widget/RemoteViews.html por lo tanto, mi recomendación para crear una clase separada para manejar todo el AppWidget las actualizaciones de IU… aquí es un simple ejemplo que he publicado hoy: stackoverflow.com/questions/7560265/…

4 Kommentare

  1. 40

    Después de un largo tiempo, tengo libre para resolver este problema.

    Aquí es lo que yo hice.

    FlashlightWidgetProvider clase :

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

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

    Permiso requerido en Manifest.xml de archivo :

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

    También registrar los receptores en Manifest.xml de archivo :

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

    Nota importante : Este código funciona perfecto si tu teléfono tiene FLASH_MODE_TORCH compatibles.

    He probado en Samsung Galaxy Ace 2.2.1 & 2.3.3. El código no está funcionando debido a que el dispositivo no tiene FLASH_MODE_TORCH.

    Funciona bien en el HTC Salsa, Wildfire..

    Si alguien puede probar y publicar los resultados aquí, sería mejor.

    • Esto ayudó mucho también para comprobar si el flash está en simplemente hacer esto:String x = params.getFlashMode();… Si x es torch entonces es on si x es off entonces es off.
    • El widget deja de funcionar después de un par de horas.. o al instante si puedo cambiar la fecha. Me pueden ayudar con esto?
  2. 6

    La mejor técnica para el manejo de los clics de un RemoteViews es crear un PendingIntent que llama a un servicio, y realizar las «cosas» que desee en el servicio, incluyendo cualquier adicional RemoteViews actualizaciones para su widget. Usted puede enviar a lo largo de los datos pertinentes en la intención de extras. El servicio de llamadas stopSelf() al final, por lo que se apaga.

    Usted no puede mantener un estado en un BroadcastReceiver; el sistema se ejecuta en la rosca, y no mantener ninguna referencia a la instancia después de llamar a onReceive(). Su mCamera variable, no está garantizada para ser mantenido entre invocaciones de su BroadcastReceiver.

    Si usted realmente necesita para mantener el estado, debe hacerlo en el servicio, y no uso stopSelf() (hasta un tiempo apropiado).

    Usted no necesita un subproceso de interfaz de usuario para utilizar el Camera clase, a menos que usted está haciendo de la imagen de vista previa, que requiere un SurfaceHolder (e implica un interfaz de usuario). Usted debe, sin embargo, tiene un bucle de eventos activos, o Camera no va a publicar las devoluciones de llamada para usted, que es un problema ya que Camera es principalmente asincrónica. Usted puede hacer esto dentro de un servicio (ver HandlerThread) y mantener el servicio activo hasta el momento de release() todo. Lo que subproceso llama a Camera.open() recibirá devoluciones de llamada.

    Hicieron todos en el momento de leer la sección sobre la Aplicación de los Widgets?
    http://developer.android.com/guide/topics/appwidgets/index.html

    El uso de la AppWidgetProvider Clase sección dice bastante más de lo que yo estoy diciendo aquí.

  3. 2

    Tuve una situación similar donde tengo que ejecutar cierto código android en el subproceso de interfaz de usuario … que sólo está disponible en una Actividad. Mi solución – una actividad con total transparencia en el diseño. Por lo que acaba de ver la pantalla de inicio (aunque no responde) mientras usted completa de sus acciones, que en su caso debe ser bastante rápido.

    • Lo que explica es el mismo que la respuesta anterior. No quiero hacer de realizar la tarea como esta. ¿Hay alguna solución adecuada ?
    • Creo que usted entiende mal. Lo que usted está tratando de hacer NO puede trabajar. El contexto de un Widget tiene un ciclo de vida muy corto, así que creo que su código puede morir a mitad de camino. Hay muy pocas cosas que usted realmente puede ejecutar en el contexto de un Widget. Todo lo demás debe ser activado por una Intención.
  4. 1

    Tengo una solución que no es muy grande, pero funciona. Tener el widget de llamar a una Actividad, y en la Actividad activa el flash, y más tarde se cierra la Actividad. El mismo para apagarlo. Si esto funciona en la Actividad, entonces esta solución funciona. No es elegante, pero funciona. He probado.

    • Gracias por la respuesta. Pero yo no quiero tener el widget de esta manera.
    • Ver mi respuesta anterior! Esa es la forma en que la aplicación widget sistema está pensado para ser utilizado. He escrito un montón de widgets, todos los cuales funcionan de esa manera. Cuanto antes se abrazan, más pronto usted puede hacer!

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea