Android相机开发

Android相机开发

推荐几个好的图片选择+拍照的框架
bilibili/boxing
LuckSiege/PictureSelector5900多个star
jeasonlzy/ImagePicker3600多个star
sucese/phoenix有Camera1和Camera2使用
只有相机功能
CameraKit/camerakit-android3900多个star
natario1/CameraView自由度很高的相机

申请权限

<uses-permission android:name="android.permission.CAMERA" />
<!--可以防止APP被安装到没有相机的Android设备上(目前仅Google Play支持)-->
<uses-feature android:name="android.hardware.camera" />

动态权限不要忘了

创建一个可以预览的界面

1.创建一个新工程

2.在新创建的工程中activity中布局文件

<FrameLayout
    android:id="@+id/preview_f"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

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信息

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

代码如下

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<Camera.Size> 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<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats();
for (Integer supportedPreviewFormat : supportedPreviewFormats) {
    Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片预览格式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "照片分辨率-----------");
List<Camera.Size> 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<Integer> supportedPictureFormats = parameters.getSupportedPictureFormats();
for (Integer supportedPreviewFormat : supportedPictureFormats) {
    Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片格式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "视频分辨率-----------");
List<Camera.Size> 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<String> 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<String> supportedFlashModes = parameters.getSupportedFlashModes();
for (String supportedFlashMode : supportedFlashModes) {
    Log.d("123===", "闪光模式--->" + supportedFlashMode);
}
Log.d("123===", "支持闪光灯模式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "支持白平衡-----------");
List<String> supportedWhiteBalance = parameters.getSupportedWhiteBalance();
for (String s : supportedWhiteBalance) {
    Log.d("123===", "--->" + s);
}
Log.d("123===", "支持白平衡-----------");
Log.d("123===", "");
Log.d("123===", "");

Log.d("123===", "场景-----------");
List<String> supportedSceneModes = parameters.getSupportedSceneModes();
for (String s : supportedSceneModes) {
    Log.d("123===", "--->" + s);
}
Log.d("123===", "场景-----------");
Log.d("123===", "");
Log.d("123===", "");

拍照,视频,对焦

假如需要使用原生拍照功能的话,Camera#takePicture()

拍照和视频都是网上那一套流程,具体的因为时间原因暂时先这样了。

相机预览和保存注意事项

下面三张图片引用自:Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能

  • 相机预览方向
相机预览方向
  • 采集的图像方向
采集的图像方向
  • 前置摄像头预览与保存一致
前置摄像头预览与保存一致

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容