Widget para encender / apagar la linterna de la cámara en android
Estoy desarrollando un widget para encender / apagar cámara led de teléfono.
He hecho un widget que puede funcionar como botón de conmutación (encendido / apagado).
- Android: no se puede abrir el contenido: file: /// storage / emulated / 0
- Actualización de un Widget a intervalos cortos utilizando API 19+
- AsyncTask para actualizar widget - cómo acceder a textviews en onPostExecute ()?
- Mostrar widgets en la vista de mapa
- Android Widget usando Cordova
El comportamiento es como sigue: A veces la luz led permanece encendida cuando habilito el widget. Pero no enciende / apaga la cámara, pero cambia el icono.
No soy capaz de averiguar cuál es el problema real.
Lo mismo funciona bien en Actividad (Torch Light Application).
¿Puede alguien por favor explicarme cómo puedo resolver mi problema?
¿A dónde voy mal?
Usted puede mirar el código 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
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; } }
- Tamaño incorrecto de la cuadrícula del widget
- Copia de seguridad y restaurar widgets pantalla de inicio y fondo de pantalla en vivo
- Utilice PreferenceActivity para configurar widget, ¿cómo recuperar las preferencias?
- Widget de Android no se actualizará
- Widget del reproductor de música de Android
- Widget simple de Android que inicia la actividad
- Cómo construir un widget de pantalla de inicio de Android?
- ¿Cómo crear un widget de Android con opciones?
Después de mucho tiempo, tuve libertad para resolver este problema.
Esto es lo que hice.
Clase 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 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 ie 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 registre los 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
soportado.
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 mejor.
La mejor técnica para manejar los clics desde una RemoteViews
es crear una PendingIntent
que llama a un servicio y realizar las "cosas" que desea en el servicio, incluyendo cualquier actualización de RemoteViews
adicional para su widget. Puede enviar a lo largo de los datos pertinentes en los extras de la 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 los ejecuta en cualquier subproceso 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 use stopSelf()
(hasta un momento apropiado).
No necesitas un subproceso de interfaz de usuario para usar la clase Camera
, a menos que estés haciendo previsualización de imágenes, lo que requiere un SurfaceHolder
(e implica una UI). Debe, sin embargo, tener un bucle de eventos activo o la Camera
no publicará devoluciones de llamada, lo cual es un problema ya que la Camera
es básicamente asíncrona. Puede hacerlo dentro de un servicio (ver HandlerThread
) y mantener su servicio funcionando hasta que sea el momento de release()
todo. Cualquiera que sea el hilo llamado Camera.open()
recibirá devoluciones de llamada.
¿Todos leen la sección de Widgets de aplicaciones? http://developer.android.com/guide/topics/appwidgets/index.html
Usar la sección de la clase AppWidgetProvider dice prácticamente lo que estoy diciendo aquí.
Tuve una situación similar en la que necesito ejecutar cierto código de android en el hilo de interfaz de usuario … que sólo está disponible en una actividad. Mi solución – una actividad con un diseño completamente transparente. Así que acaba de ver su pantalla de inicio (aunque no responde) mientras completa sus acciones, que en su caso debe ser bastante rápido.
Tengo una solución que no es grande, pero funciona. Haga que el widget llame a una Actividad y, en Actividad, active el flash y cierre la Actividad. Lo mismo para apagarlo. Si esto funciona en la actividad entonces esta solución funcionará. No es elegante, pero funciona. Lo intenté.
- ADT 22.2 Asistente para nuevas aplicaciones: dependencia de plantilla no admitida: actualiza tu complemento de Android Eclipse
- El proyecto no tiene un archivo default.properties! Editar las propiedades del proyecto para establecer una