您的位置:首页 > 其它

nexus 5和三星Galaxy S4等中打开手电筒无效的解决方案

2014-11-07 16:13 330 查看
      吐槽一下:好几天都被一个卡死的bug烦恼,一直以为是自己写的有问题,后来找到原因才发现是我们程序自己的bug。很无语啊,他们在网上随便找了一个卸载反馈的功能加到我们程序中来,没想到这个功能导致内存泄漏,还影响了其他的功能。觉得现在在公司也学不到什么技术了,没有牛人,原来的框架也是把开源的框架拿过来改一下,自己完成的这个功能,也是老大随便找了一个类似的,然后交给我自己改,来实现我们的需求,呵呵,这样真的好吗。还好是在试用期,还是可以跳槽的。。(吐槽结束,接续码代码)

      最近项目需要做一个手电筒的附加小功能,想想应该很简单,网上copy了一段代码如下:

private void SetFlashlight(boolean isOpen){
try {
PackageManager pm = getApplicationContext().getPackageManager();
if(pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){
Camera camera = null;
try {
//getCamera中会调用Camera.open()来获取Camera
camera = getCamera();
Camera.Parameters mParameters = camera.getParameters();
if (mParameters.getFlashMode() == null) {
//TODO
} else {
if (isOpen) {
camera.startPreview();
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(mParameters);
} else {
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(mParameters);
camera.stopPreview();
//调用Camera的release()方法
removeCarema();
}
isFlashlightOn = isOpen;
}

}catch (Exception e){
if(camera != null) {
camera.release();
}
}
}else {
//TODO
}
}catch (Exception e){
}
}


       原理比较简单,调用Camera的闪关灯来实现手电筒的功能。先判断是否支持闪光的的属性,然后通过设置FlashMode 为FLASH_MODE_TORCH和FLASH_MODE_OFF来打开和关闭闪光灯。

      特别注意:在关闭的时候记得调用Camera的release方法,否则可能出现后续使用Camera的时候无法连接到Camera的异常。

      拿小米手机测试后发现可以使用手电筒了,于是顺利的交差了。

      后来发现测试给报了个bug,在nexus 5 中手电筒是无效的,三星Galaxy S4已出现了。瞬间心寒了一下,看来网上随便找的的都不怎么靠谱啊。。

     一步步调试找原因,发现nexus 5 中的设置FlashMode都正常,打开手电筒时设置为FLASH_MODE_TORCH,关闭时设为FLASH_MODE_OFF,按理说应该能正常打开和关闭的啊。使用了一下它的相机,闪光灯表现也正常啊,为嘛程序里面不能打开呢,难道是我打开的方式不对?

     没办法,只能求助谷歌了,于是各种谷歌,各种http://stackoverflow.com上查找原因啊。

     找到另外一个手电筒的方案,是用反射调用ServiceManager的IHardwareService$Stub接口。部分代码如下:

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);
setFlashlightEnabled.invoke(svc, ture);


       发现在nexus 5上还是无效。。

       空欢喜一场,继续查找答案。。在stackoverflow中惊奇的找到一个答案: “I had the same problem and solved it via using Surface View having 1px width and 1px height”,我们需要一个SurfaceView。

       在camera.startPreview();之前增加 camera.setPreviewTexture(new SurfaceTexture(0))  ,问题解决。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息