teléfono samsung para movimiento movil linterna encender desaparecio con celular agitar agitando activar android android-widget widget android-camera android-appwidget

samsung - Widget para encender/apagar la linterna de la cámara en Android



linterna del teléfono (4)

Tengo una solución que no es genial, pero funciona. Haga que el widget llame una Actividad, y en la Actividad encienda el flash, y luego cierre la Actividad. Lo mismo para apagarlo. Si esto funciona en la Actividad, esta solución funcionará. No es elegante, pero funciona. Lo intenté.

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

He creado un widget que puede funcionar como el botón de alternar (activar / desactivar).

El comportamiento es el siguiente: A veces, la luz LED permanece encendida cuando habilito el widget. Pero no enciende / apaga la cámara led pero cambia el ícono.

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

Lo mismo funciona bien en Actividad (Aplicación de luz de antorcha).

¿Alguien puede explicarme cómo puedo resolver mi problema?

Donde me estoy equivocando?

Puedes mirar el código de abajo que he hecho hasta ahora

método onUpdate

@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 onReceive es el siguiente:

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

método processOffClick

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

método processOnClick

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


Tuve una situación similar en la que necesito ejecutar cierto código de Android en el hilo de UI ... que solo está disponible en una Actividad. Mi solución: una actividad con un diseño completamente transparente. Así que solo ve su pantalla de inicio (aunque no responda) mientras completa sus acciones, que en su caso deberían ser bastante rápidas.


La mejor técnica para manejar clics desde un RemoteViews es crear un PendingIntent que llame a un servicio y realizar las "cosas" que desee en el servicio, incluidas las actualizaciones adicionales de RemoteViews para su widget. Puede enviar los datos relevantes en los extras de intención. El servicio llama a stopSelf() al final, por lo que se apaga.

No puede mantener ningún estado en un BroadcastReceiver ; el sistema ejecuta esos en cualquier hilo disponible, y no mantiene ninguna referencia a su instancia después de llamar a onReceive() . No se garantiza que su variable mCamera se mantenga entre las invocaciones de su BroadcastReceiver .

Si realmente necesita mantener el estado, debe hacerlo en el servicio y no utilizar stopSelf() (hasta el momento apropiado).

No necesita un subproceso de interfaz de usuario para usar la clase de Camera , a menos que esté haciendo una vista previa de la imagen, que requiere un SurfaceHolder (e implica una interfaz de usuario). Sin embargo, debe tener un bucle de eventos activo, o la Camera no le enviará devoluciones de llamadas, lo cual es un problema ya que la Camera es principalmente asincrónica. Puede hacerlo dentro de un servicio (consulte HandlerThread ) y mantener su servicio en funcionamiento hasta que sea el momento de release() todo. Cualquiera que sea el hilo que llame a Camera.open() recibirá devoluciones de llamada.

¿Alguien realmente leyó la sección sobre Aparatos de la aplicación? http://developer.android.com/guide/topics/appwidgets/index.html

Usar la sección Clase AppWidgetProvider dice más o menos lo que estoy diciendo aquí.


Después de un largo tiempo, tuve la libertad de resolver este problema.

Aquí esta lo que hice.

Clase de 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.widget_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds, views); } }

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

Permiso requerido en el archivo Manifest.xml :

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

También registra receptores en el archivo Manifest.xml :

<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 su teléfono tiene FLASH_MODE_TORCH compatible.

He probado en Samsung Galaxy Ace 2.2.1 y 2.3.3. El código no funciona porque ese dispositivo no tiene FLASH_MODE_TORCH.

Funciona bien en HTC Salsa, Wildfire ..

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