Android-手电筒应用小思路(一)

来源:互联网 发布:java web分页完整代码 编辑:程序博客网 时间:2024/06/09 20:55

         Android 手电筒应用应该算是一个非常简单的应用。所以就不做太多说明。手电筒应用主要知识点就是Camera(硬件)的使用,控制闪光灯来达到手电筒的效果。本人不才,前面有翻译过关于Camera的官方文档,虽然翻译的比较粗糙,但是还是能明白大概意思--- Android官方开发指南-Camera(相机)。

很显然,手电筒应用的主要控制代码如下:

protected void openTorchLight(){        try {            if (mCamera == null) {                mCamera = Camera.open();                int textureID = 0;                mCamera.setPreviewTexture(new SurfaceTexture(textureID));                mCamera.startPreview();                mParameters = mCamera.getParameters();                mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);                mCamera.setParameters(mParameters);            }        } catch (IOException e) {            e.printStackTrace();        }    }    protected void closeTorchLight(){        if(mCamera != null){            mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);            mCamera.setParameters(mParameters);            mCamera.release();            mCamera = null;        }    }
然后就是在打开手电筒的时候调用openTorchLight()函数,在关闭手电筒的时候调用closeTorchLight()函数,当然 还要在activity的部分生命周期函数中做处理。然而我就思考,这是否就是 最优的方式。所以我自己有两个疑问:

        1、Camera 在任何机器上都是秒开起吗?

2、这样打开Camera是在主线程,一单Camera出现问题,打开延迟好多,那主线程是否就会ANR,或者出其它问题。

        对于第一个问题,配置高的手机可以接近让camera秒开启。但是配置低的手机,特别是低端手机,打开camera的时候,就能很明显的感觉到打开camera所需要的时间。

所以就有必要很好的控制camera什么时候打开,什么时候关闭。比如在手电筒应用主界面,打开和关闭手电筒,除了第一次要打开camera以外,其它就不用再次打开camera,这样做,就只要在离开手电筒主界面的时候 释放camera就好!

  对于第二个问题,在Android中主线程,也就是UI线程。所以还是有一点的风险的。如果读过Android 照相机应用源码的朋友肯定知道,Android源码照相机应用是在一个Thread中打开Camera的。


说太多都不如代码来的实际,所以针对以上两点我直接贴代码(代码只包括.java代码,):

package com.example.torchlight;import android.app.Activity;import android.content.pm.PackageManager;import android.graphics.Point;import android.graphics.SurfaceTexture;import android.graphics.drawable.TransitionDrawable;import android.hardware.Camera;import android.os.Bundle;import android.os.PowerManager;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.ImageView;import android.widget.Toast;import java.io.IOException;public class TorchActivity extends Activity implements OnClickListener{    private final static String TAG = "TorchActivity";    private ImageView mImageViewTorchLight;    private ImageView mImageViewTorchLightControler;    private Camera mCamera;    private Camera.Parameters mParameters;    private PowerManager.WakeLock mWakeLock;    private CameraOpenThread cameraOpenThread;    private boolean torchstate;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_torch);        torchstate = true;        mImageViewTorchLight = (ImageView) findViewById(R.id.imageview_torchlight);        mImageViewTorchLightControler = (ImageView) findViewById(R.id.imageview_torchlight_controler);        mImageViewTorchLightControler.setOnClickListener(this);        //set the flag of this window        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);        PowerManager mPowerManager = (PowerManager) this.getSystemService(this.POWER_SERVICE);        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);        mWakeLock.acquire();        //set the Rect of controlling to open or close flash light        Point mPoint = new Point();        getWindowManager().getDefaultDisplay().getSize(mPoint);        ViewGroup.LayoutParams layoutParams= (ViewGroup.LayoutParams)mImageViewTorchLightControler.getLayoutParams();        layoutParams.height = mPoint.y * 3 / 4;        layoutParams.width = mPoint.x / 3;        mImageViewTorchLightControler.setLayoutParams(layoutParams);        if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){            if(mCamera == null){                cameraOpenThread = new CameraOpenThread();                cameraOpenThread.start();            }        }        mImageViewTorchLight.setTag(true);    }    protected void onClick_TorchLight(){        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)){            Toast.makeText(this, this.getResources().getString(R.string.toast_prompt), Toast.LENGTH_LONG).show();        }        if(((boolean)mImageViewTorchLight.getTag()) == false){            openTorchLight();        } else{            closeTorchLight();        }    }    protected void openTorchLight(){        TransitionDrawable mTransitionDrawable = (TransitionDrawable) mImageViewTorchLight.getDrawable();        mTransitionDrawable.reverseTransition(200);        mImageViewTorchLight.setTag(true);        if(mCamera != null){            mParameters.setFlashMode(mParameters.FLASH_MODE_TORCH);            mCamera.setParameters(mParameters);        }    }    protected void closeTorchLight(){        TransitionDrawable mTransitionDrawable = (TransitionDrawable)mImageViewTorchLight.getDrawable();        if(((boolean)mImageViewTorchLight.getTag()) == true){            mTransitionDrawable.startTransition(200);            mImageViewTorchLight.setTag(false);            if(mCamera != null){                mParameters.setFlashMode(mParameters.FLASH_MODE_OFF);                mCamera.setParameters(mParameters);            }        }    }    protected void openCamera(){        try {            if (mCamera == null) {                mCamera = Camera.open();                int textureID = 0;                mCamera.setPreviewTexture(new SurfaceTexture(textureID));                mCamera.startPreview();                mParameters = mCamera.getParameters();                mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);                mCamera.setParameters(mParameters);            }        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.imageview_torchlight_controler){            onClick_TorchLight();        }    }    protected class CameraOpenThread extends Thread{        @Override        public void run() {            //super.run();            openCamera();        }    }    protected void releaseCamera(){        if(mCamera != null){            mCamera.release();            mCamera = null;        }        if(cameraOpenThread != null){            cameraOpenThread.isInterrupted();            cameraOpenThread = null;        }        if(mWakeLock != null){            mWakeLock.release();            mWakeLock = null;        }        torchstate = false;    }    @Override    protected void onPause() {        super.onPause();        releaseCamera();    }    @Override    protected void onDestroy() {        super.onDestroy();    }    @Override    protected void onResume() {        super.onResume();        if(!torchstate){            if(mCamera == null){                cameraOpenThread = new CameraOpenThread();                cameraOpenThread.start();                torchstate = true;            }        }    }}


说明:

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">1、因为是独立应用,所以在onPause()的时候就要释放掉camera,否则其它应用就不能成功调用camera了。</span>

2、PowerManager mPowerManager = (PowerMananger)this.getSystemService(this.POWER_SERVICE);

      mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);

      mWakeLock.acquire();

      这段代码是让手机灭屏以后仍保持cpu的运作,否则手机完全进入休眠状态,cpu停止运作,很有可能会导致手机crash 或者重启。因为cpu停止运作就会suspend camera。而此时手电筒仍在后台开启,两者就会产生矛盾。  


 ps:其它资源和布局文件没贴出来。整个demo我已经上传(http://download.csdn.net/detail/u013656135/8726413 )。

     有不足之处请谅解和指点,谢谢!


0 0
原创粉丝点击