4

我试图打开 LED 闪光灯,但 LED 闪光灯在延迟几秒钟后开机。

我的手机里有一个内置的手电筒,当我点击它时,闪光灯会立即亮起。

这里有什么问题?

这是我的代码:

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

                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) {
                    mCamera.stopPreview();
                    mCamera.release();
                }
            }
        }

DroidLED 类:

import java.lang.reflect.Method;

import android.os.IBinder;

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

我从stackoverflow的一些答案中获取了这段代码。

感谢你的协助!

4

2 回答 2

0

摩托罗拉的延迟高吗?

这只是一个猜测,但 DroidLED 构造函数调用了昂贵的系统初始化。你不能这样做吗?

public class MyWidgetClickHandler {
    private DroidLED = null;
    public MyWidgetClickHandler(string ManuName) {
        // This is slow. It will run once at initialization.
        if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
            DroidLED = new DroidLED();
    }

    public void processOnClick() {
        if (DroidLED != null)
            DroidLED.enable(true);
        else
            ; // ... TODO
    }

    public void processOffClick() {
        if (DroidLED != null)
            DroidLED.enable(false);
        else
            ; // ... TODO
    }
}

可能还有更多。例如,您可以创建一个LED interfacewithenableisEnabled,并为其提供两个实现。一个是DroidLED,另一个是CommonCameraLED。有了这个,它看起来像这样:

public class LEDFactory {
    public static LED createLED(string ManuName) {
        if (ManuName != null && ManuName.toLowerCase().contains("motorola"))
            return new DroidLED();
        else
            return new CommonCameraLED();
    }
}

public class MyWidgetClickHandler {
    private LED myLed = null;
    public MyWidgetClickHandler(string ManuName) {
        myLed = LEDFactory.createLED(ManuName);
    }

    public void processOnClick() {
        myLed.enable(true);
        // NOTHING TO DO
    }

    public void processOffClick() {
        myLed.enable(false);
        // NOTHING TO DO
    }
}

您还可以创建一个线程进行初始化,这样手机就不会启动缓慢。

于 2013-10-09T07:14:15.380 回答
0

我刚遇到同样的问题并找到了解决方案,但我使用三星 Galaxy S2 进行了测试。此代码应适用于所有设备。

分析每个功能,我发现设置相机所需的一些调用,延迟总计500 毫秒,使得频闪效果不可能。

我的解决方案是将所有这些函数移动到我想要获取相机时调用的单独函数,并将“打开”代码减少到对Camera.setParameters(). 通过这样做,延迟下降到只有4ms

例如(简化代码只是为了证明这一点):

// First get the camera for your app (Keep this variables as class 

members so the live between functions)
private void acquireCamera()
{
    try
    {
        // Get camera
        cam = Camera.open(); 
        // This is not on your code but you should do it for compatibility
        mSurfaceTexture = new SurfaceTexture(0);
        cam.setPreviewTexture(mSurfaceTexture);
        cam.startPreview();
        camParams = cam.getParameters();
    }
    catch(IOException e)
    { /*...*/ }
}

// Then turn on / off as many times you want.
private void setTorch(boolean on)
{
    camParams.setFlashMode(on? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF);
    cam.setParameters(camParams);
}

// Finally release the camera when you`re done
private void releaseCamera
{
    camParams = null;
    cam.stopPreview();
    mSurfaceTexture = null;
    cam.release();
}
于 2014-04-13T08:11:40.410 回答