Android相机开发
推荐几个好的图片选择+拍照的框架
bilibili/boxing
LuckSiege/PictureSelector5900多个star
jeasonlzy/ImagePicker3600多个star
sucese/phoenix有Camera1和Camera2使用
只有相机功能
CameraKit/camerakit-android3900多个star
natario1/CameraView自由度很高的相机
申请权限
动态权限不要忘了
创建一个可以预览的界面
1.创建一个新工程
2.在新创建的工程中activity中布局文件
3.创建一个相机预览的view 继承SurfaceView
最新都开始用TextureView,关于SurfaceView/TextureView
- SurfaceView是一个有自己Surface的View。界面渲染可以放在单独线程而不是主线程中。它更像是一个Window,自身不能做变形和动画。
- TextureView同样也有自己的Surface。但是它只能在拥有硬件加速层层的Window中绘制,它更像是一个普通View,可以做变形和动画。
更多关于SurfaceView与TextureView区别的内容可以参考这篇文章Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView.
官方给出的方案,图片来自于Android平台Camera开发实践指南:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private final SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//surface第一次创建时回调
//打开相机
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//surface变化的时候回调(格式/大小)
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//surface销毁的时候回调
mHolder.removeCallback(this);
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
4.在activity中添加
public class MainActivity extends AppCompatActivity {
private FrameLayout mFrameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initCamera();
}
private void initCamera() {
CameraPreview preview = new CameraPreview(this);
mFrameLayout.addView(preview);
}
private void initView() {
mFrameLayout = (FrameLayout) findViewById(R.id.preview_f);
}
}
至此可以显示一个相机界面,并有图像显示。
添加偏好设置
如分辨率、闪光灯、对焦等。
通过当前界面的相机camera对象获取起设置的参数getParameters()
预览分辨率
-
parameters.getSupportedPreviewSizes()
获取相机支持的所有预览分辨率
预览格式
具体参照ImageFormat或者自己Google
-
parameters.getSupportedPreviewFormats()
获取相机支持的所有预览格式
照片分辨率
-
parameters.getSupportedPictureSizes()
获取相机支持的所有图片分辨率
图片格式
具体参照ImageFormat或者自己Google
-
parameters.getSupportedPictureFormats()
获取相机支持的所有图片格式
视频分辨率
parameters.getSupportedVideoSizes()
获取相机支持的所有视频分辨率
对焦模式
-
parameters.getSupportedFocusModes()
获取相机支持的所有对焦模式
曝光补偿
-
parameters.getMinExposureCompensation()
获取相机支持的最低曝光补偿 -
parameters.getMaxExposureCompensation()
获取相机支持的最高曝光补偿
闪光灯模式
-
parameters.getSupportedFlashModes()
获取相机支持的闪光灯模式
白平衡
-
parameters.getSupportedWhiteBalance()
获取相机支持的白平衡
场景
parameters.getSupportedSceneModes()
获取相机支持的场景
声明GPS权限
想要拍到的照片中包含GPS信息
代码如下
int numberOfCameras = Camera.getNumberOfCameras();
Log.d("123===", "相机个数===" + numberOfCameras);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
//后置:0 CAMERA_FACING_BACK; 前置:1 CAMERA_FACING_FRONT
Log.d("123===", "当前相机信息=" + cameraInfo.facing);
}
Camera camera = mPreview.getCamera();
Camera.Parameters parameters = camera.getParameters();
Log.d("123===", "预览分辨率-----------");
List supportedPreviewSizes = parameters.getSupportedPreviewSizes();
for (Camera.Size previewSize : supportedPreviewSizes) {
Log.d("123===", previewSize.width + "---" + previewSize.height);
}
Log.d("123===", "预览分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "获得相机支持的图片预览格式-----------ImageFormat");
List supportedPreviewFormats = parameters.getSupportedPreviewFormats();
for (Integer supportedPreviewFormat : supportedPreviewFormats) {
Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片预览格式-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "照片分辨率-----------");
List supportedPictureSizes = parameters.getSupportedPictureSizes();
for (Camera.Size pictureSize : supportedPictureSizes) {
Log.d("123===", pictureSize.width + "---" + pictureSize.height);
}
Log.d("123===", "照片分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "获得相机支持的图片格式-----------ImageFormat");
List supportedPictureFormats = parameters.getSupportedPictureFormats();
for (Integer supportedPreviewFormat : supportedPictureFormats) {
Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片格式-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "视频分辨率-----------");
List supportedVideoSizes = parameters.getSupportedVideoSizes();
for (Camera.Size supportedVideoSize : supportedVideoSizes) {
Log.d("123===", supportedVideoSize.width + "---" + supportedVideoSize.height);
}
Log.d("123===", "视频分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "对焦模式-----------ImageFormat");
List supportedFocusModes = parameters.getSupportedFocusModes();
for (String supportedFocusMode : supportedFocusModes) {
Log.d("123===", supportedFocusMode + "");
}
Log.d("123===", "对焦模式-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "曝光补偿-----------");
int minExposureCompensation = parameters.getMinExposureCompensation();
int maxExposureCompensation = parameters.getMaxExposureCompensation();
Log.d("123===", "最高=" + maxExposureCompensation);
Log.d("123===", "最低=" + minExposureCompensation);
Log.d("123===", "曝光补偿-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "支持闪光灯模式-----------");
List supportedFlashModes = parameters.getSupportedFlashModes();
for (String supportedFlashMode : supportedFlashModes) {
Log.d("123===", "闪光模式--->" + supportedFlashMode);
}
Log.d("123===", "支持闪光灯模式-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "支持白平衡-----------");
List supportedWhiteBalance = parameters.getSupportedWhiteBalance();
for (String s : supportedWhiteBalance) {
Log.d("123===", "--->" + s);
}
Log.d("123===", "支持白平衡-----------");
Log.d("123===", "");
Log.d("123===", "");
Log.d("123===", "场景-----------");
List supportedSceneModes = parameters.getSupportedSceneModes();
for (String s : supportedSceneModes) {
Log.d("123===", "--->" + s);
}
Log.d("123===", "场景-----------");
Log.d("123===", "");
Log.d("123===", "");
拍照,视频,对焦
假如需要使用原生拍照功能的话,Camera#takePicture()
拍照和视频都是网上那一套流程,具体的因为时间原因暂时先这样了。
相机预览和保存注意事项
下面三张图片引用自:Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能
- 相机预览方向
![](http://img.e-com-net.com/image/info10/2a7c6c8be5354d7a8035b6e9739d3cfb.jpg)
- 采集的图像方向
![](http://img.e-com-net.com/image/info10/6f5f387b3c6747a09cdcd2d1f9ff0096.jpg)
- 前置摄像头预览与保存一致
![](http://img.e-com-net.com/image/info10/30138da221c74cbca90b495effcc7d2a.jpg)
参考
- Android相机开发系列
- Android Camera相机开发详解
- Android: Camera相机开发详解(上) —— 知识储备
- Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能
- Android 相机(二): 最详细的自定义相机的步骤拆解
- Android平台Camera开发实践指南 这有Camera2的知识
- Android设备对新Camera2 API的支持问题:以华为M2为例