Android手电筒(闪光灯)

本文详细介绍了如何在Android设备上实现手电筒功能,重点讲解了通过调整Camera参数以开启闪光灯的方法,并提供了完整的代码示例及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

百度google一下现有的关于手电筒(实际上是闪光灯控制)的设计和源代码都有很多。

例如

http://www.oschina.net/code/snippet_107931_17160

http://blog.youkuaiyun.com/pengcheng_liu/article/details/23860679

Camera.Parameters param = mCamera.getParameters();
param.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(param);
mCamera.startPreview();

通过设置Camera的FLASH_MODE参数,可以将闪光灯设置为常亮状态,再用startPreivew()方法打开照相机的预览,就可以成功打开闪光灯。

但实际上这些方法只能适配部分机型,而Google Nexus 5、 HTC 部分机型等手机使用这些代码都不能打开闪光灯。

察看Android开发者文档,在Camera的class overview中可以看到我们忽略掉的部分

http://developer.android.com/intl/zh-cn/reference/android/hardware/Camera.html

To take pictures with this class, use the following steps:

1.Obtain an instance of Camera from open(int).
2.Get existing (default) settings with getParameters().
3.If necessary, modify the returned Camera.Parameters object and call setParameters(Camera.Parameters).
4.If desired, call setDisplayOrientation(int).
5.Important: Pass a fully initialized SurfaceHolder to setPreviewDisplay(SurfaceHolder). Without a surface, the camera will be unable to start the preview.
6.Important: Call startPreview() to start updating the preview surface. Preview must be started before you can take a picture.
7.When you want, call takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback) to capture a photo. Wait for the callbacks to provide the actual image data.
8.After taking a picture, preview display will have stopped. To take more photos, call startPreview() again first.
9.Call stopPreview() to stop updating the preview surface.
10.Important: Call release() to release the camera for use by other applications. Applications should release the camera immediately in onPause() (and re-open() it in onResume()).

看到第五点(important),如果没有在startPreview之前调用setPreviewDisplay。照相机就不会启动预览。

所以问题解决,适用于市面上大部分机型的相机开启,需要在startPreview之前setPreivewDisplay:

Camera.Parameters param = mCamera.getParameters();
param.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(param);
mCamera.setPreviewDisplay(mHolder); //重要!在startPreview要调用
mCamera.startPreview();

为setPreviewDisplay(SurfaceHolder holder) 传入的SurfaceHolder参数需要在setPreviewDisplay前初始化完成:
private WindowManager mWindowManager;
private SurfaceHolder mHolder;
private MySurfaceView mFlashTorchSurface;

private void createSurfaceView() {
     if (mFlashTorchSurface != null) {
         return;
     }
     try {
         mWindowManager = (WindowManager) mContext
         .getSystemService(Context.WINDOW_SERVICE); // 获取WindowManager
         // 添加手电筒所需要的SurfaceView
         mFlashTorchSurface = new MySurfaceView(mContext);
         // 由于会在SurfaceView中进行预览,所以将背景色设置为黑色,使用户看不到
         mFlashTorchSurface.setBackgroundColor(Color.BLACK);
         WindowManager.LayoutParams mCallViewParams = new WindowManager.LayoutParams(); // 设置LayoutParams(全局变量)相关参数
         mCallViewParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
         mCallViewParams.format = PixelFormat.RGBA_8888; // 设置透明背景
         mCallViewParams.width = 1;
         mCallViewParams.height = 1;
         mCallViewParams.gravity = Gravity.RIGHT | Gravity.TOP;
         mCallViewParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
             | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 让当前View失去焦点
             mWindowManager.addView(mFlashTorchSurface, mCallViewParams);
     } catch (Exception ex) {
         ex.printStackTrace();
         mFlashTorchSurface = null;
     }
 }

/**
 * 手电筒需要的surface
 */
 private class MySurfaceView extends SurfaceView implements
 SurfaceHolder.Callback {

     public MySurfaceView(Context context) {
         super(context);
         initHolder();
     }

     private void initHolder() {
     // 注册surfaceCreated、surfaceChanged、surfaceDestroyed回调方法
         SurfaceHolder holder = getHolder();
         holder.addCallback(this);
         holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 在某些机型上,这一项必须设置
     }

     @Override
     public void surfaceCreated(SurfaceHolder holder) {
         mHolder = holder;
     }

     @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int width,
     int height) {
     }

     @Override
     public void surfaceDestroyed(SurfaceHolder holder) {
     mHolder = null;
     }
 }

这样,大部分机型都可以打开手电筒了。

完整的打开关闭方法如下:

public void powerOn() {
//打开手电
    initCamera(); //初始化相机
    createSurfaceView();  //初始化SurfaceHolder
    setLightOn(); //打开手电
}

private void initCamera() {
    try {
        mCamera = Camera.open();
    } catch (Exception e) {
        mCamera = null;
    }
    if (mCamera == null) {
        mIsAvailable = false;
    } else {
        mIsAvailable = true;
    }
}

private void setLightOn() {
    if (mCamera == null) {
        return;
    }
    try {
        // 防止startPreview、setParameters抛出RuntimeException异常导致崩溃
        Camera.Parameters param = mCamera.getParameters();
        param.setFlashMode(Parameters.FLASH_MODE_TORCH);
        mCamera.setParameters(param);
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        powerOff();
        return;
    }
}

public void powerOff() {
//关闭手电,手电使用结束后必须释放camera资源,否则会造成内存泄露
    setLightOff();//关灯并释放资源
    if (mCamera != null) { //保护
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    removeSurfaceView(); //释放SurfaceHodler
}

private void setLightOff() {
    if (mCamera == null) {
        return;
    }
    try {
        // 防止startPreview、setParameters抛出RuntimeException异常导致崩溃
        Camera.Parameters param = mCamera.getParameters();
        param.setFlashMode(Parameters.FLASH_MODE_OFF);
        mCamera.setParameters(param);
        mCamera.stopPreview();
        mCamera.release();
    } catch (RuntimeException e) {
        e.printStackTrace();
        mCamera.stopPreview();
        mCamera.release();
    }
    mCamera = null;
    mIsLight = false;
}

private void removeSurfaceView() {
    if (mFlashTorchSurface != null) {
        mWindowManager.removeViewImmediate(mFlashTorchSurface);
        mFlashTorchSurface = null;
    }
}

当然还要加上相关权限:

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

原地址: http://codesblock.com/blog/?p=56




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值