您的位置:首页 > 移动开发 > Android开发

安卓之相机Camera(二)

2016-06-16 13:12 501 查看
之前说过的,调用手机摄像头拍照除了调用系统的照相之外,也可以自己去自定义我们的相机软件。这里开始看官方api觉得云里雾里的,现在看懂了,恍然大悟,其实官方都已经给我们罗列了核心的方法和思路。

1 首先,因为是自定义的,所以需要给我们的manifest文件加上一些必要的权限。

<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2 我们来定义这样的一个视图,用来显示的,这个类中我们通过外部去传入camera对象,然后对camera进行一些必要的设置,通过mCamera.startPreview();方法来进行捕捉视图,里面的方法在官方文档中都是有的,我也就是复制过来的。没什么说的,另外实现SurfaceHolder.Callback这个接口,复写三个方法,分别用于不同阶段进行一些处理

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{

private SurfaceHolder mHolder;
private Camera mCamera;

public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}

// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}

// set preview size and make any resize, rotate or
// reformatting changes here

// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e){

}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}
}
3 mainActivity的布局文件  framelayout用来添加自定义的view,两个按钮分别用于拍照 和继续拍照

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
<Button
android:id="@+id/button_cancle"
android:text="Cancle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
<ImageView
android:id="@+id/iv"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitXY"
/>

</LinearLayout>

</LinearLayout>
4 主类MainActivity

public class MainActivity extends Activity{
private Camera mCamera;
private CameraPreview mPreview;
private Button button_capture;
private ImageView iv;
private File pictureFile;
private Button button_cancle;
private PictureCallback mPicture = new PictureCallback() {
<span style="white-space:pre">	</span>//向文件输出位置存放io 输出流
@Override
public void onPictureTaken(byte[] data, Camera camera) {

pictureFile = getOutputMediaFile();

if (pictureFile == null){
return;
}

try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {

} catch (IOException e) {

}
iv.setImageURI(Uri.fromFile(pictureFile));
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

button_capture = (Button) findViewById(R.id.button_capture);
button_cancle = (Button) findViewById(R.id.button_cancle);
iv = (ImageView) findViewById(R.id.iv);
if(checkCameraHardware(this)){
mCamera = getCameraInstance();//实例化
mPreview = new CameraPreview(this, mCamera);//初始化
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);//添加自定义的view
preview.addView(mPreview);
}
button_capture.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
button_cancle.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
mCamera.startPreview();//继续捕捉视图
}
});
}
<span style="white-space:pre">	</span>//设置存放的文件路径,和之前那个一样
protected File getOutputMediaFile() {
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"ABC";
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp ;
File file2 = new File(file,imageFileName+".jpg");
return file2;
}
<span style="white-space:pre">	</span>//检查是否有摄像头设备 或者权限
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
//实例化 这个Camera 对象 然后传给那个自定义view
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
//应用关闭后 释放掉照相机 防止其他软件不能正常使用
@Override
protected void onDestroy() {
mCamera.release();
super.onDestroy();
}

}
因为默认的照相机 是横屏的,官方给的是在manifest清单文件的activity标签下,加入 android:screenOrientation="landscape"这个属性,但是我个人认为这样,手机 看起来很变扭,所以没有这么做,用官方提供的,mCamera.setDisplayOrientation(90); 这个方法,是屏幕是竖直的效果,不过最后在现实图片发现,我们只是假象的以为拍摄的是竖直的,其实还是颠倒的,我通过查看那个获取的图片发现。只是给我们认为是那个样子,所以后面我们就需要将图片也翻转过来,这个暂时还没有去做。另外当我们获取了图片时,需要重新开启,通过再次调用mCamera.startPreview();这个方法。

点击下载源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息