EasyCamera--更简单更灵活的相机应用编写

时间:2022-09-11 13:30:08

最近开工做项目了,需要前期准备下技术,项目中需要用到Camera的相关技术,偶然在GitHub上发现了这个东西--EasyCamera,使得调用相机的相关操作变得更加简单了。

这样我们先把Github上的文件先clone一下,将zip文件下载下来,然后解压,由于这个项目还是用的Eclipse构建,用Eclipse的用户就可以跳过这一段了。

为了构建方便我们自己新建一个Library的Module,这样走File->New Module到达下面这个页面:

EasyCamera--更简单更灵活的相机应用编写

按照图片中选中的点击Next,然后需要给你的Library来一个名字,然后到达这个页面:

EasyCamera--更简单更灵活的相机应用编写

选择Add No Activity,然后直接点击Finish即可。这样我们的Library就创建好了。

我想说的是为何这么做?昨天在研究的时候,因为用到了.aar作为EasyCamera的库,并没有找到合适的方法导入.aar文件,导致自己在这个问题上浪费了不少时间,所以还是选择了这样一种方式来引入,方便而且更快捷。

下边就是需要创建我们的工程Module了,在第一张图上点击Phone And Tablet Application的选项,这样一步步创建好就OK了。

然后是在工程中引入我们刚才创建的库,这个不是很麻烦的问题,请参考我的这篇文章Android Studio--引用自己创建的Library

这样基本上万事具备了,我们需要将我们下载的zip文件解压,将下图所示的三个文件拷贝到Library中的java代码位置:

EasyCamera--更简单更灵活的相机应用编写

好了这样我们就能正常引用这个EasyCamera的库了。

这时候前期准备工作正式完成。下面我们来写一个相机的实例来感受一下。

首先先附上布局文件activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<SurfaceView
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>

<Button
android:id="@+id/btn_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>

</LinearLayout>
布局文件很简单,不做过多解释,就是一个相机预览和拍照按钮。

然后附上MainActivity.java的代码:

import library.DefaultEasyCamera;
import library.EasyCamera;

import android.content.Context;
import android.hardware.Camera;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;


public class MainActivity extends ActionBarActivity {

private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;

private Button capture;


/**
* 判断是否在预览状态
*/
private boolean previewIsRunning = false;

private EasyCamera mEasyCamera;
private EasyCamera.CameraActions mCameraActions;

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

mSurfaceView = (SurfaceView) findViewById(R.id.camera_preview);
capture = (Button) findViewById(R.id.btn_capture);
mSurfaceHolder = mSurfaceView.getHolder();

mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {

@Override
public void surfaceCreated(SurfaceHolder holder) {
// 开启后置摄像头
mEasyCamera = DefaultEasyCamera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
// 设置相机翻转角度
// mEasyCamera.setDisplayOrientation(90);
// 正常显示相机预览
WindowManager manager = (WindowManager) MainActivity
.this.getSystemService(Context.WINDOW_SERVICE);
mEasyCamera.alignCameraAndDisplayOrientation(manager);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(!previewIsRunning && mEasyCamera != null) {
try {
// 开启预览
mCameraActions = mEasyCamera.startPreview(holder);
} catch (IOException e) {
e.printStackTrace();
}
previewIsRunning = true;
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 停止预览并释放
mEasyCamera.stopPreview();
mEasyCamera = null;
}
});

capture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EasyCamera.PictureCallback mPictureCallback = new EasyCamera.PictureCallback(){

@Override
public void onPictureTaken(byte[] data, EasyCamera.CameraActions actions) {
// 停止预览
mEasyCamera.stopPreview();
try {
// 延时1000s,看的更加清楚
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 存储图片的操作
FileOutputStream fos = null;
try {
Log.d("TAG",getExternalFilesDir(Environment.DIRECTORY_PICTURES)+File.separator+"abc.jpg");
fos = new FileOutputStream(new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)
<span style="white-space:pre"></span>+File.separator+"abc.jpg"));                            fos.write(data);                            fos.close();                        } catch (FileNotFoundException e) {                            e.printStackTrace();                        } catch (IOException e) {                            e.printStackTrace();                        }                        // 开启预览                        EasyCamera.Callbacks.create().withRestartPreviewAfterCallbacks(true);                        try {                            mEasyCamera.startPreview(mSurfaceHolder);                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                };                // 拍摄照片的操作                mCameraActions.takePicture(                        EasyCamera.Callbacks.create().withJpegCallback(mPictureCallback));            }        });    }}
最后的话需要我们把相应的permission加上,但是我们可以把这个权限加载Library中,这样我们的工程就不需要添加了!权限如下:

<uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>

好了,这样我们来看一下运行效果,

EasyCamera--更简单更灵活的相机应用编写

中间发生了一个小错误,就是在运行时点击中间的home键退出时,再次进入程序发生了崩溃的现象,深入查看代码的时候,是自己释放相机的时候考虑的不够周全,现在对于自己的代码做出这样的修改:

 <span style="white-space:pre"></span>@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("TAG","surfaceDestroyed停止并释放");
// 停止预览并释放
mEasyCamera.stopPreview();
mEasyCamera.release();
mEasyCamera = null;
mCameraActions = null;
previewIsRunning = false;
}
而且在代码头部mEasyCamera = null,这样修改后,问题就不大了。在修改的过程中,你可能会发现,没有Camera的release的相应代码,这样我们就修改下源代码了。

首先我们在EasyCamera接口中添加release方法,如下:

    /**
* 释放相机的方法
*/
void release();
然后在DefaultCamera中来实现这个方法:

    @Override
public void release() {
camera.release();
}
这样简单的一修改我们就可以在自己的代码中将相机完美的释放了!

怎么样是不是很简单啊?

这里附上我的源代码下载地址

参考文章:http://techblog.bozho.net/fixing-the-android-camera-api/ 英文好的朋友可以直接过来读!