2011-03-31 10 views
53

Estoy tratando de usar la linterna LED de las cámaras en un widget. He encontrado varios hilos sobre este tema (es decir the one se menciona más adelante ..), ahora estoy tratando de controlar la luz usando:Utilice la linterna de la cámara en Android

Camera cam = Camera.open();  
Parameters p = cam.getParameters(); 
p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
cam.setParameters(p); 
cam.release(); 

En el AndroidManifest.xml trataron diferentes permisos, actualmente tengo:

<uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.FLASHLIGHT"/> 
<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" /> 
<uses-feature android:name="android.hardware.camera.flash" /> 

Estoy probando esto en mi Galaxy Tab ya que no tengo ningún otro dispositivo Android a mano: la luz no se enciende. Así que ahora tengo algunas preguntas:

  1. ¿Hay alguna manera de probar el comportamiento de la luz led en el emulador?
  2. ¿Estoy haciendo algo mal aquí?
  3. Según la pregunta this que trata del mismo problema, funciona de manera diferente en el Galaxy Tab. ¿Cómo?
  4. Y, por último, si funciona de manera diferente, estoy empezando a preguntarme si es solo la Galaxy Tab o si otros dispositivos usan métodos diferentes también. Sería difícil probarlo entonces y me parece bastante extraño.

¡Gracias por cualquier idea!

Por cierto, probé rápidamente con quick-settings que se menciona aquí algunas veces. La linterna tampoco funciona con configuraciones rápidas.

Tenga en cuenta que el Galaxy Tab stil usa Android 2.2. Veo que hubo algunos cambios entre 2.2 y 2.3.

comentario: Sé que tiene que funcionar de alguna manera, ya que he encontrado otras aplicaciones en el mercado que funcionan perfectamente con el Galaxy Tab.

Comentario 2: Si configuro cam.setParameters (p); y solicite directamente a la cámara el estado actual con getFlashMode() devuelve FLASH_MODE_TORCH correctamente. Sin embargo, si suelto la cámara y la vuelvo a abrir, devuelve FLASH_MODE_OFF. Es casi como si el objeto de la cámara conociera la solicitud pero realmente no la transmitiera al hardware.

-

Después comentario Konstantins, quité la cam.release(); parte. Tiene razón, la configuración no persiste si sueltas la cámara. Si usa cam.open() nuevamente, obtendrá una instancia nueva con la luz apagada. Sin embargo, la luz aún no funciona en la pestaña galaxia. Entonces, supongo que es difícil mantener la luz encendida si estás tratando de controlarlo a través de un widget. Tan pronto como finalice el servicio en segundo plano, el objeto de la cámara se liberará automáticamente y, por lo tanto, la luz se apagará nuevamente. Mis preguntas aún permanecen, especialmente por qué la cámara no se enciende en primer lugar.

+0

Incluso yo quería saber cómo hacer esto. ¡Voto ascendente! – CuriousMind

+0

No tengo ninguna idea también, pero si no puede encontrar una solución, puede descargar una de las aplicaciones de linterna del mercado y tratar de descompilarla. – RoflcoptrException

+3

Bueno, antes de iniciar el código de alguien de ingeniería inversa, realmente me gustaría obtener más información de los codificadores en stackoverflow ;-) – pgruetter

Respuesta

34

Cada dispositivo es un poco diferente. A Samsung especialmente le gusta complicar las cosas a los desarrolladores de aplicaciones.

En el Galaxy Tab que debe ser bueno con:

Camera cam; 
void ledon() { 
    cam = Camera.open();  
    Parameters params = cam.getParameters(); 
    params.setFlashMode(Parameters.FLASH_MODE_ON); 
    cam.setParameters(params); 
    cam.startPreview(); 
    cam.autoFocus(new AutoFocusCallback() { 
       public void onAutoFocus(boolean success, Camera camera) { 
       } 
      }); 
} 

void ledoff() { 
    cam.stopPreview(); 
    cam.release(); 
} 

Si eso no funciona, entonces puede ser una cuestión de establecer FLASH_MODE_OFF inicialmente y cambiar después de la startPreview.

+0

Muchas gracias por los detalles. Una prueba rápida no mostró ningún éxito. Lo probaré en una sola actividad para asegurarme de que nada interfiera. ¿Puede decirme de dónde obtiene esta información? ¿Lo has probado en un Galaxy Tab? – pgruetter

+1

Sí. Soy el desarrollador de TeslaLED, que en realidad necesita una actualización para el Tab y aún no tuve la oportunidad de lanzarlo, pero hago lo mismo que antes y lo he probado en un T-Mobile Galaxy Tab. Comienzo con FLASH_MODE_OFF y cambio a FLASH_MODE_ON sin embargo. –

+0

@Kevin TeslaCoil: estaba enfrentando el mismo problema pero su código funcionó para mí en Samsung Galaxy Ace 2.2.1. Pero el LED permanece en estado ON por solo 5 segundos ... ¿Cuál puede ser el motivo? –

18

No debe soltar la cámara después de establecer los parámetros. Descubrí que el flash está activado (en modo antorcha) después de haber comenzado la vista previa. (Se aplica a motorola desafiar, 2.1)

También es una buena idea comprobar los modos de flash compatibles, antes de intentar activarlos.

Enredarse con la configuración de la cámara en Android es el vudú más oscuro: muchos dispositivos se comportan de manera diferente y parece que no hay una forma confiable de atacarlos a todos con una sola pieza de código.La apuesta más segura es configurar siempre la cámara correctamente cuando se llame al método onResume(). También consideraría hacer lo mismo en enConfigChange(), porque al menos el bloqueador de pantalla Motorola puede forzar su aplicación al modo retrato, reiniciándola por completo.

P.s. Supongo que cuando cierras la cámara, la aplicación de la cámara nativa se cierra y luego se recrea en un estado fresco.

+0

¡Muchas buenas sugerencias, gracias! Sin soltar la instancia de la cámara, ahora puedo pedir las propiedades y vuelve correctamente al modo de la antorcha, ¡genial! Sin embargo, la linterna todavía no se enciende, incluso cuando se utiliza la vista previa. La cuestión es que estoy intentando encender la luz LED a través de un widget. Esto será difícil en función de sus comentarios, ya que necesito sujetar el objeto de la cámara siempre que la luz permanezca encendida. – pgruetter

+0

Jugué con la linterna en mi pequeña aplicación de OCR y encontré que el flash se enciende solo cuando comencé la vista previa (y se apagó cuando solicité una instantánea, produciendo así una imagen en negro). Desarrollé una pequeña aplicación de demostración de Android en el proyecto JavaOCR. No dudes en obtener inspiración de ella: http://sourceforge.net/projects/javaocr/ –

+0

¡Genial! Muchas gracias por el enlace. Le echaré un vistazo. – pgruetter

8

Esto funciona para mí en un HTC Desire ... (con 2,2) (Por supuesto, con la cámara y la linterna permisos):

Camera mycam = Camera.open(); 
    Parameters p = mycam.getParameters();// = mycam.getParameters(); 
    p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
    mycam.setParameters(p); //time passes 
    try { 
     Thread.sleep(500); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    p.setFlashMode(Parameters.FLASH_MODE_OFF); 
    mycam.release(); 
+0

¿Con qué dispositivo Android estás intentando esto? ¡Gracias! – pgruetter

+0

@Horaceman No funciona en un Samsung Galaxy SII: ¿te falta algo por casualidad? ¿Como mostrar la vista previa? – AgentKnopf

4

También podría intentar agregar una vista de superficie. Por favor, eche un vistazo a mi respuesta a LED flashlight on Galaxy Nexus controllable by what API?

+0

Probé con el Samsung Galaxy SII y no funcionó.Los enfoques mucho más simples funcionaron en otros teléfonos (Nota, Xperia S), es un dolor: P ... – AgentKnopf

+0

Para mí está trabajando en el SII, ¿está visible su superficie? – timoschloesser

+0

Sí lo es. Intenté todas las variaciones posibles. El caso es que funcionó en otros teléfonos (también su muestra) pero no en ese SII (al menos no en el que tengo aquí). Lo curioso es que también utilizamos la cámara para otros fines dentro de un diálogo de cámara adecuado. Si ejecuté ese código de la linterna, entonces comencé el diálogo de la cámara, la linterna se mostró. Primero pensé en SurfaceView, pero como lo intenté y no funcionó, tal vez sea otra cosa. Me resulta bastante espeluznante que no exista una forma simple y unificada de hacer que la linterna funcione en todos los dispositivos compatibles con linterna. – AgentKnopf

1
private Camera camera; 
void openCam(){ 
    camera = Camera.open(); 
    if (camera != null) { 
     Camera.Parameters params = camera.getParameters(); 
     camera.setParameters(params); 
    } 
    Camera.Parameters p = camera.getParameters(); 
    p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
    camera.setParameters(p); 
} 

conjunto de permisos en Manifiesto:

<uses-permission 
    android:name="android.permission.FLASHLIGHT" 
    android:permissionGroup="android.permission-group.HARDWARE_CONTROLS" 
    android:protectionLevel="normal" /> 

<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.flash" /> 
11

lo he hecho de la siguiente manera, que funciona en muchos teléfonos:

String manuName = android.os.Build.MANUFACTURER.toLowerCase(); 
Camera mCamera; 

El siguiente código muestra, cómo apagar y encender las luces:

private void processOnClick() { 

    if (manuName.contains("motorola")) { 
     DroidLED led; 
     try { 
      led = new DroidLED(); 
      led.enable(true); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } else { 
     if (mCamera == null) { 
      try { 
       mCamera = Camera.open(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     if (mCamera != null) { 

      final Parameters params = mCamera.getParameters(); 

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

      if (flashModes == null) { 
       return; 
      } else { 
       if (count == 0) { 
        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 { 
         // Toast.makeText(this, 
         // "Flash mode (torch) not supported",Toast.LENGTH_LONG).show(); 

         params.setFlashMode(Parameters.FLASH_MODE_ON); 

         mCamera.setParameters(params); 
         try { 
          mCamera.autoFocus(new AutoFocusCallback() { 
           public void onAutoFocus(boolean success, Camera camera) { 
            count = 1; 
           } 
          }); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 

    if (mCamera == null) { 
     return; 
    } 
} 

private void processOffClick() { 

    if (manuName.contains("motorola")) { 
     DroidLED led; 
     try { 
      led = new DroidLED(); 
      led.enable(false); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } else { 
     if (mCamera != null) { 
      count = 0; 
      mCamera.stopPreview(); 
     } 
    } 
} 

A continuación se muestra la clase DroidLED:

class DroidLED { 

    private Object svc = null; 
    private Method getFlashlightEnabled = null; 
    private Method setFlashlightEnabled = null; 

    @SuppressWarnings("unchecked") 
    public DroidLED() throws Exception { 
      try { 
        // call ServiceManager.getService("hardware") to get an IBinder for the service. 
        // this appears to be totally undocumented and not exposed in the SDK whatsoever. 
        Class sm = Class.forName("android.os.ServiceManager"); 
        Object hwBinder = sm.getMethod("getService", String.class).invoke(null, "hardware"); 

        // get the hardware service stub. this seems to just get us one step closer to the proxy 
        Class hwsstub = Class.forName("android.os.IHardwareService$Stub"); 
        Method asInterface = hwsstub.getMethod("asInterface", android.os.IBinder.class); 
        svc = asInterface.invoke(null, (IBinder) hwBinder); 

        // grab the class (android.os.IHardwareService$Stub$Proxy) so we can reflect on its methods 
        Class proxy = svc.getClass(); 

        // save methods 
        getFlashlightEnabled = proxy.getMethod("getFlashlightEnabled"); 
        setFlashlightEnabled = proxy.getMethod("setFlashlightEnabled", boolean.class); 
      } 
      catch(Exception e) { 
        throw new Exception("LED could not be initialized"); 
      } 
    } 

    public boolean isEnabled() { 
      try { 
        return getFlashlightEnabled.invoke(svc).equals(true); 
      } 
      catch(Exception e) { 
        return false; 
      } 
    } 

    public void enable(boolean tf) { 
      try { 
        setFlashlightEnabled.invoke(svc, tf); 
      } 
      catch(Exception e) {} 
    } 

}

Los siguientes permisos se debe establecer en su AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.FLASHLIGHT"/> 
<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" /> 
<uses-feature android:name="android.hardware.camera.flash" /> 
+4

Sin haber probado este enfoque: si usa el reflejo, es muy probable que su código se rompa tarde o temprano. – AgentKnopf

+0

Desde: https://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java – hB0

+0

Esto no es una solución a prueba de futuro como lo hacen todas las soluciones Reflection. Tarde o temprano, Google cerrará el boquete y los métodos de reflexión como estos simplemente no funcionarán. – ChuongPham

Cuestiones relacionadas