精华内容
下载资源
问答
  • 2021-06-05 16:05:09

    Android相机开发指南(三)

    这篇是这个指南中比较短的一篇,其实对于从相册中取出一张图片来显示实在是没什么难的。

    使用 Intent.ACTION_PICK你可以通过android的 content provider 获取各类多媒体文件。在本例中,我们将使用ACTION_PICK执行一个基本操作:打开Android图片库,选择一个图像,显示在ImageView上。相关代码在示例工程中有。

    打开SimpleAndroidPickerFragment 文件,你可以看到:

    @Override

    publicvoidonClick(Viewview){

    Intenti=newIntent(Intent.ACTION_PICK,

    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

    startActivityForResult(i,IMAGE_PICKER_SELECT);

    }

    /**

    * Photo Selection result

    */

    publicvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

    if(requestCode==IMAGE_PICKER_SELECT&&resultCode==Activity.RESULT_OK){

    MainActivityactivity=(MainActivity)getActivity();

    Bitmapbitmap=getBitmapFromCameraData(data,activity);

    mSelectedImage.setImageBitmap(bitmap);

    }

    }

    从上边代码可以看到,当Fragment中的按钮被触发,一个Intent就会被分发去从EXTERNAL_CONTENT_URI 中获取一类媒体。当Activity result返回时,我们就可以保存并显示bitmap在我们的ImageView上。

    这有部分保存bitmap的逻辑:

    /**

    * Use for decoding camera response data. *

    *

    * @param data

    * @param context

    * @return

    */

    publicstaticBitmapgetBitmapFromCameraData(Intentdata,Contextcontext){

    UriselectedImage=data.getData();

    String[]filePathColumn={

    MediaStore.Images.Media.DATA

    };

    Cursorcursor=context.getContentResolver().query(selectedImage,filePathColumn,null,

    null,null);

    cursor.moveToFirst();

    intcolumnIndex=cursor.getColumnIndex(filePathColumn[0]);

    StringpicturePath=cursor.getString(columnIndex);

    cursor.close();

    returnBitmapFactory.decodeFile(picturePath);

    }

    这里有点小逻辑需要注意一下,基本上我所做的是使用cursor,调用cursor.moveToFirst() 来查询‘last selected image’,这种方法会自动获取我们从相册中选取的图片。然后通过BitmapFactory进行转码。

    翻译:@flyouting

    时间:2014/03/19

    源地址

    更多相关内容
  • Android相机开发

    千次阅读 2019-03-21 00:29:02
    文章目录Android相机开发申请权限创建一个可以预览的界面1.创建一个新工程2.在新创建的工程中activity中布局文件3.创建一个相机预览的view 继承SurfaceView4.在activity中添加添加偏好设置预览分辨率预览格式照片...

    Android相机开发

    申请权限

    <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相机开发详解(中) ——实现预览、拍照、保存照片等功能

    • 相机预览方向

    相机预览方向

    • 采集的图像方向

    采集的图像方向

    • 前置摄像头预览与保存一致

    前置摄像头预览与保存一致

    参考

    展开全文
  • Android相机开发详解(一)Android相机开发详解(一)请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)Android相机开发能够实现打开相机,前后摄像头切换,摄像预览...

    Android相机开发详解(一)

    Android相机开发详解(一)

    请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)

    Android相机开发能够实现打开相机,前后摄像头切换,摄像预览,保存图片,浏览已拍照图片等相机功能。

    Android相机开发详解(一)主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能。

    Android相机开发详解(二)主要实现翻页浏览相片,触控缩放浏览图片,删除图片,发送图片等四个功能。

    Android相机开发详解(三)主要实现录像,视频保存,自动对焦,闪光灯控制等四个功能

    效果图:

    2311251019.png

    1、CameraActivity的布局文件,使用FrameLayout布局(activity_camera.xml)

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".CameraActivity" >

    android:id="@+id/fragmentContainer_camera"

    android:layout_width="match_parent"

    android:layout_height="match_parent" />

    2、CameraActivity相机不存在的布局文件(activity_no_camera.xml)

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".CameraActivity" >

    android:gravity="center"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:text="未检查到本地有摄像头" />

    3、CameraActivity类(CameraActivity.java)

    a)请求窗口特性:无标题

    b)添加窗口特性:全屏

    c)检查摄像头是否存在。根据检查结果进行布局

    package com.example.camerademo;

    import android.annotation.SuppressLint;

    import android.app.Activity;

    import android.content.Intent;

    import android.content.pm.PackageManager;

    import android.hardware.Camera;

    import android.os.Build;

    import android.os.Bundle;

    import android.support.v4.app.FragmentActivity;

    import android.view.Window;

    import android.view.WindowManager;

    import android.widget.Toast;

    public class CameraActivity extends FragmentActivity {

    private final static int REQUEST_DELETE_PHOTO = 1;

    @SuppressLint("NewApi")

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    // TODO Auto-generated method stub

    //请求窗口特性:无标题

    requestWindowFeature(Window.FEATURE_NO_TITLE);

    //添加窗口特性:全屏

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    super.onCreate(savedInstanceState);

    //检查摄像头是否存在。

    PackageManager pm = getPackageManager();

    boolean hasCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) ||

    pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||

    Build.VERSION.SDK_INT>Build.VERSION_CODES.GINGERBREAD ||

    Camera.getNumberOfCameras()>0;

    //根据检查结果进行布局

    if (!hasCamera) {

    setContentView(R.layout.activity_no_camera);

    return;

    }

    setContentView(R.layout.activity_camera);

    android.support.v4.app.FragmentManager fm = getSupportFragmentManager();

    android.support.v4.app.Fragment fragment = fm.findFragmentById(R.id.fragmentContainer_camera);

    if (fragment==null) {

    fragment = new CameraFragment();

    fm.beginTransaction().add(R.id.fragmentContainer_camera, fragment).commit();

    }

    }

    }

    4、CameraFragment的布局文件(fragment_camera.xml)

    a)使用FrameLayout布局,双层布局

    b)顶层是一个SurfaceView,用来拍照预览

    c)底层是FrameLayout布局,包含两个ImageButton,一个ProgressBar进度条控件

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    android:id="@+id/camera_surfaceView"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:layout_weight="1"/>

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:clickable="true">

    android:id="@+id/camera_rotationview_button"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="left|top"

    android:layout_marginTop="16dp"

    android:layout_marginLeft="16dp"

    android:background="@drawable/button_camera_rotationview"

    />

    android:id="@+id/camera_takepicture_button"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="right|top"

    android:layout_marginTop="16dp"

    android:layout_marginRight="16dp"

    android:background="@drawable/button_camera_takepicture"

    />

    android:id="@+id/camera_view_button"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="right|bottom"

    android:layout_marginBottom="16dp"

    android:layout_marginRight="16dp"

    android:background="@drawable/button_camera_view"

    />

    android:id="@+id/camera_progressContainer"

    style="@android:style/Widget.ProgressBar.Large"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="center"

    />

    5、CameraFragment类(CameraFragment.java)

    a)相机是一种系统级别的重要资源,因此,很重要一点:需要时使用,用完及时释放。如果忘记释放,除非重启设备,否则其他应用将无法使用相机。

    b)保险起见,我们在onResume()方法中打开相机,在onPause()方法中释放相机。Camera类中打开相机的方法有两个。

    i.         open()方法在API第9级以下的级别使用。

    ii.         open(int)方法在第9级及第9级以上的级别使用,传入参数0开打设备可用的第一相机(通常指的是后置相机),传入参数1开打设备可用的第二相机(通常指的是前置相机)

    c)使用SurfaceView类配合相机来实现摄像预览。需要实现SurfaceHolder接口,并设置Surface类型:setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)。但该方法和该常量在API第11级别就已经被弃用。我们使用@SuppressWarnings("deprecation")注解来消除弃用代码的相关警告。

    d)SurfaceHolder是我们与Surface对象联系的纽带。Surface对象代表着原始像素数据的缓冲区。SurfaceView出现在屏幕上时,会创建Surface,这时我们需要把Camera连接到SurfaceHolder上;SurfaceView从屏幕上消失时,Surface随机被销毁,我们再将Camera从SurfaceHolder断开。注意:Surface不存在时,必须保证没有任何内容要在它上面绘制。理想工作状态如图:

    2311251020.png

    e)为了完成以上任务,SurfaceHolder提供了另一个接口:SurfaceHolder.Callback。该接口有三个方法用来监听Surface生命周期中的事件。

    i.         包含SurfaceView的视图层级结构被放到屏幕上时调用该方法。也是与Camera进行关联的地方。

    public voidsurfaceCreated(SurfaceHolder surfaceHolder)

    ii.         Surface首次显示在屏幕上时调用该方法。通过传入的参数,可以知道Surface的像素格式以及它的宽度和高度。

    public voidsurfaceChanged(SurfaceHolder holder, int format, int w, int h)

    iii.         SurfaceView从屏幕上移除时,Surface也随即被销毁。也是Camera与其断开关联的地方

    public voidsurfaceDestroyed(SurfaceHolder holder)

    f)为了能与SurfaceView无缝贴合,Camera也提供了不同的方法。

    i.         为了连接Camera和Surface,设置Surface被实时预览使用setPreviewDisplay(SurfaceHolderholder)

    ii.         开始捕捉和绘制预览帧到屏幕上

    startPreview()

    iii.         停止捕捉和绘制预览帧到屏幕上

    stopPreview()

    g)使用Camera的内部类Camera.Parameters来确定预览图片和保存图片的大小

    i.         getParameters()返回这个相机的当前参数设置。

    ii.             setParameters(Camera.Parametersparams)改变这个相机的当前参数设置。

    iii.         然后自定义一个找出设备支持的最佳尺寸的方法getBestSupportedSize(List sizes,int width,int height),接受一组预览尺寸,然后穷举法找出具有最大数目像素的尺寸。

    iv.         调用Camera.Parameters类的方法。

    1.        getSupportedPictureSizes()得到图片支持的尺寸

    2.        getSupportedPreviewSizes()得到预览图片支持的尺寸

    3.        setPictureSize(int

    width, int height)设置图片的大小尺寸

    4.setPreviewSize(int

    width, int height)设置预览图片的大小尺寸

    h)使用Camera类见名知意的拍照方法takePicture(Camera.ShutterCallbackshutter,Camera.PictureCallbackraw,Camera.PictureCallbackpostview,Camera.PictureCallbackjpeg)方法

    i.         该方法会触发一个异步的图像捕捉,触发相机初始化一系列的回调机制应用于图像捕捉进程中

    ii.         该方法有四个回调方法。Camera.ShutterCallbackshutter在图像被捕捉时刻触发,它会触发一个快门声音告知用户;PictureCallbackraw在未加工图像有效时触发;Camera.PictureCallbackpostview在被按比例缩放图像有效时触发;Camera.PictureCallbackjpeg在压缩图像有效时触发。

    iii.         该方法只有在startPreview()方法调用之后才有效。该方法调用之后预览效果将会停止,如果想要再次预览或者拍摄更多相片,需要再次调用startPreview()方法。

    package com.example.camerademo;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.util.List;

    import android.annotation.SuppressLint;

    import android.app.Activity;

    import android.content.Context;

    import android.content.Intent;

    import android.hardware.Camera;

    import android.hardware.Camera.CameraInfo;

    import android.hardware.Camera.PictureCallback;

    import android.hardware.Camera.ShutterCallback;

    import android.hardware.Camera.Size;

    import android.os.Build;

    import android.os.Bundle;

    import android.support.v4.app.Fragment;

    import android.view.LayoutInflater;

    import android.view.SurfaceHolder;

    import android.view.SurfaceHolder.Callback;

    import android.view.SurfaceView;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.view.ViewGroup;

    import android.widget.ImageButton;

    public class CameraFragment extends Fragment{

    //startActivityForResult的请求常量

    private final static int REQUEST_DELETE_PHOTO = 1;

    //自定义时间类

    private MyTime mTime=new MyTime();

    //相机类

    private Camera mCamera;

    //预览视图的接口

    private SurfaceHolder mSurfaceHolder;

    //进度条控件

    private View mProgressContainer;

    //当前打开的是哪一个摄像头

    private int switchCamera=0;

    @Override

    public void onCreate(Bundle savedInstanceState) {

    // TODO Auto-generated method stub

    super.onCreate(savedInstanceState);

    }

    @SuppressWarnings("deprecation")

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container,

    Bundle savedInstanceState) {

    // TODO Auto-generated method stub

    //生成fragment视图

    View v = inflater.inflate(R.layout.fragment_camera, container,false);

    //隐藏进度条控件

    mProgressContainer = v.findViewById(R.id.camera_progressContainer);

    mProgressContainer.setVisibility(View.INVISIBLE);

    //显示最新照片的缩略图的按钮实例化

    ImageButton viewButton = (ImageButton) v.findViewById(R.id.camera_view_button);

    //最新照片的缩略图的按钮监听器

    viewButton.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View arg0) {

    // TODO Auto-generated method stub

    // 跳转ViewPagerActivity,请求ViewPagerActivity执行删除图片操作

    Intent i = new Intent();

    i.setClass(getActivity(), ViewPagerActivity.class);

    startActivityForResult(i, REQUEST_DELETE_PHOTO);

    }

    });

    //切换镜头按钮实例化

    ImageButton rotationViewButton = (ImageButton) v.findViewById(R.id.camera_rotationview_button);

    //切换镜头按钮监听器

    rotationViewButton.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View arg0) {

    // TODO Auto-generated method stub

    //如果摄像头数目小于等于1,该按钮无效,返回

    if (Camera.getNumberOfCameras() <= 1) {

    return ;

    }

    if(switchCamera == 1) {

    //停掉原来摄像头的预览,并释放原来摄像头

    mCamera.stopPreview();

    mCamera.release();

    mCamera = null;

    //打开当前选中的摄像头

    switchCamera = 0;

    mCamera = Camera.open(switchCamera);

    try {

    //通过surfaceview显示取景画面

    mCamera.setPreviewDisplay(mSurfaceHolder);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    //开始预览

    mCamera.startPreview();

    }else {

    //停掉原来摄像头的预览,并释放原来摄像头

    mCamera.stopPreview();

    mCamera.release();

    mCamera = null;

    //打开当前选中的摄像头

    switchCamera = 1;

    mCamera = Camera.open(switchCamera);

    try {

    //通过surfaceview显示取景画面

    mCamera.setPreviewDisplay(mSurfaceHolder);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    //开始预览

    mCamera.startPreview();

    }

    }

    });

    //照相按钮实例化

    ImageButton takePictureButton = (ImageButton) v.findViewById(R.id.camera_takepicture_button);

    //照相按钮监听器

    takePictureButton.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View arg0) {

    // TODO Auto-generated method stub

    if (mCamera!=null) {

    //相机的拍照方法

    mCamera.takePicture(

    //第一个回调方法,快门回调方法

    new ShutterCallback() {

    @Override

    public void onShutter() {

    // TODO Auto-generated method stub

    //该方法回触发快门声音告知用户,并设置进度条显示

    mProgressContainer.setVisibility(View.VISIBLE);

    }

    }

    //第二个,第三个回调方法为空

    , null,null,

    //最后一个回调方法,jpg图像回调方法

    new PictureCallback() {

    @Override

    public void onPictureTaken(byte[] date, Camera camera) {

    // TODO Auto-generated method stub

    //根据当前时间自定义格式生成文件名

    String filename = mTime.getYMDHMS()+".jpg";

    //文件输出流

    FileOutputStream os = null;

    //默认文件保存成功

    boolean success = true;

    try {

    //私有打开应用沙盒文件夹下文件

    os = getActivity().openFileOutput(filename, Context.MODE_PRIVATE);

    //写文件

    os.write(date);

    } catch (Exception e) {

    // TODO: handle exception

    success = false;

    }finally{

    try {

    if (os != null) {

    os.close();

    }

    } catch (Exception e) {

    // TODO: handle exception

    success = false;

    }

    }

    if (success) {

    //如果文件保存成功,进度条隐藏

    mProgressContainer.setVisibility(View.INVISIBLE);

    //再次预览

    try {

    mCamera.startPreview();

    } catch (Exception e) {

    // TODO: handle exception

    mCamera.release();

    mCamera=null;

    }

    }

    }

    });

    }

    }

    });

    //预览视图实例化

    SurfaceView mSurfaceView = (SurfaceView) v.findViewById(R.id.camera_surfaceView);

    //得到预览视图接口

    mSurfaceHolder = mSurfaceView.getHolder();

    //设置预览视图接口类型

    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    //添加预览视图接口的回调程序,监听视图的生命周期

    mSurfaceHolder.addCallback(new Callback() {

    @Override

    public void surfaceCreated(SurfaceHolder surfaceHolder) {

    // TODO Auto-generated method stub

    //当SurfaceView的视图层级结构被放到屏幕上时候,连接Camera和Surface

    try {

    if (mCamera!=null) {

    mCamera.setPreviewDisplay(surfaceHolder);

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    }

    @Override

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    // TODO Auto-generated method stub

    //当Surface首次显示在屏幕上时候,设置好相机参数,开始预览

    if (mCamera==null) {

    return;

    }

    Camera.Parameters parameters = mCamera.getParameters();

    Size s = getBestSupportedSize(parameters.getSupportedPreviewSizes(), w, h);

    parameters.setPreviewSize(s.width, s.height);

    s = getBestSupportedSize(parameters.getSupportedPictureSizes(), w, h);

    parameters.setPictureSize(s.width, s.height);

    mCamera.setParameters(parameters);

    try {

    mCamera.startPreview();

    } catch (Exception e) {

    // TODO: handle exception

    mCamera.release();

    mCamera=null;

    }

    }

    @Override

    public void surfaceDestroyed(SurfaceHolder holder) {

    // TODO Auto-generated method stub

    //当视图从屏幕上移除的时候,停止预览

    if (mCamera!=null) {

    mCamera.stopPreview();

    }

    }

    });

    return v;

    }

    /******************************************]

    *

    * 穷举法找出具有最大数目像素的尺寸

    *

    * @param sizes

    * @param width

    * @param height

    * @return

    */

    public Size getBestSupportedSize(List sizes,int width,int height) {

    Size bestSize = sizes.get(0);

    int largestArea = bestSize.width*bestSize.height;

    for (Size s :sizes) {

    int area =s.width*s.height;

    if (area>largestArea) {

    bestSize=s;

    largestArea = area;

    }

    }

    return bestSize;

    }

    //接收活动结果,响应startActivityForResult()

    @Override

    public void onActivityResult(int request, int result, Intent mIntent) {

    // TODO Auto-generated method stub

    if (request == REQUEST_DELETE_PHOTO) {

    if (result == Activity.RESULT_OK) {

    // 跳转ViewPagerActivity,请求ViewPagerActivity执行删除图片操作

    int requestCode = 1;

    Intent i = new Intent();

    i.setClass(getActivity(), ViewPagerActivity.class);

    startActivityForResult(i, requestCode);

    }

    }

    }

    @Override

    public void onPause() {

    // TODO Auto-generated method stub

    super.onPause();

    System.out.println("onPause");

    //程序中止暂停时,释放Camera

    if (mCamera!=null) {

    mCamera.release();

    mCamera=null;

    }

    }

    @Override

    public void onDestroy() {

    // TODO Auto-generated method stub

    super.onDestroy();

    System.out.println("onDestroy");

    }

    @Override

    public void onStop() {

    // TODO Auto-generated method stub

    super.onStop();

    System.out.println("onStop");

    }

    @SuppressLint("NewApi")

    @Override

    public void onResume() {

    // TODO Auto-generated method stub

    super.onResume();

    //程序运行时,打开Camera

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {

    mCamera = Camera.open(switchCamera);

    }else {

    mCamera = Camera.open();

    }

    }

    }

    6、添加权限和Activity特性(AndroidMainfest.xml)

    a)权限:

    b)     Activity特性:

    android:screenOrientation="landscape"

    请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)

    学习《Android编程权威指南》心得与笔记                    by2015.2.10早

    1楼cheyiliu3天前 20:57markRe: kangweijian前天 13:47回复cheyiliunwhat?

    展开全文
  • android 相机开发

    2014-07-31 10:32:53
    基于Android 开发相机功能,可拍照存储。
  • :person_running: BGACamera-Android :person_running: Android相机开发学习笔记,参考
  • Android Camera 相机开发第一篇

    千次阅读 2020-09-02 11:45:32
    相机现实知识: Camera SurfaceView (SurfaceView 也是TextureView,最常用的当然是SurfaceView 所以主讲SurfaceView) 俩者关系脑图 一、SurfaceView 、Surface 、 SurfaceHolder 关系图 S...

    相机显示知识:

    1.      Camera
    2.      SurfaceView  (SurfaceView 也是TextureView,最常用的当然是SurfaceView 所以主讲SurfaceView)

                                                                                                俩者关系脑图

    一、SurfaceView 、Surface 、 SurfaceHolder

    关系图

     

    Surface 

          Surface用来处理屏幕内容合成器所管理的原始缓存区的工具,由图像缓冲区的消费者(如:Surfacetexture)创建然后移交给生产者(如MeddiaPlayer) 或者是显示到(如:CameraDevice)

     SurfaceHoler

    抽象接口,给持有surface的对象使用,可以控制surface的大小和格式,编辑Surface种的像素,以及监听surface的变化,这个接口通过SurfaceView获得

     SurfaceHoler中有一个Callback的接口通过脑图大家可以看到,它的回调方法有3个

    • surfaceCreated(SurfaceHolder holder)                                                                                                                                         suface第一次调用的时候回调
    • surfaceChanged(SurfaceHolder holder,int format ,int width ,int height)                                                                                        surface变化的时候回调   变化为大小和格式
    • surfaceDestroyed(SurfaceHolder holder)                                                                                                                                      suface销毁的时候回调

    SurfaceView

     SurfaceView提供了嵌入视图层级种的专用Surface,我们可以控制Surface的格式和大小。

    SurfaceView则负责把Surface现实在屏幕的正确位置

    SurfaceView 其实也是继承自View,其中俩个成员变量,一个是Surface对象一个是SurfaceHolder对象。

    •  SurfaceView把Surface现实在屏幕
    • SurfaceView通过SurfaceHoder告诉我们Surface的3个状态  (创建   变化    销毁)
    • SurfaceView可以通过getHolder()方法获得当前SurfaceView的SurfaceHolder对象让就可以对SurfaceHolder对象添加回调的Surface进行监听状态
    1. SurfaceView是View的对象
    2. SurfaceView中有俩个对象,Surface和SurfaceHolder
    3. 通过getHolder()方法获得当前SurfaceView的SurfaceHolder对象

    二 、 Camera

     

    Camera类中的内部类

    CameraInfo 用来描述相机信息,通过Camera中getCameInfo(int camerald,CameraInfo cameraInfo)方法获得,主要包括一下成员变量。

    • facing                                                                                                                                                                                            facing代表相机的方向,它的值只能是CAMERA_FACING_BACK(后置摄像头)和CAMERA_FACING_FRONT(前置摄像头)。

     CAMERA_FACING_BACK(后置摄像头)和CAMERA_FACING_FRONT(前置摄像头)Camera中的静态变量

    •  orientation                                                                                                                                                                                    orientaion是相机采集的角度,他的值是采集到的图片顺时针旋转自然的角度值,它必须的0,90,180,270中的一个。        因此可以就可以知道在拿到相机拍照的时候角度为60的话那么它在怎么旋转也不是可以为正的原因。                                    
    • setDisplayOrientation                                                                                                                                                                  设置预览图片的顺时针角度。注:这个方法会影响预览图像个拍照后现实的图片,这个方法对竖屏应用和图片非常有效。然后是前摄像头在进行角度旋转之前,图像会进行一个水平的镜像反转,所以你打开相机预览图像的时候如同照镜子,但是拍下照来才发现是水平方向的镜像。                                                                                                                                              注:setDisplayOrientation(int degrees)是Camea类中的一个方法,之所以穿插在这里来讲,是为了和上面提到的orientation做一个统一讲解,因为这两个都涉及到了方向问题
    • 屏幕坐标  在Android系统中,屏幕的左上角是坐标系统的圆点(0,0)坐标。原点向右是X轴的正方向,原点向下是Y轴的正方向。
    • 自然方向 每个设备都有一个自然方向,手机和平板的自然方向不同。手机的自然方向是 portait(竖屏),平板的就是(landscape) 横屏
    • 图像传感器 (imager Sensor) 方向  手机相册的图像数据都是来自摄像头硬件的图像传感器,这个传感器被固定到手机后的一个默认的取景方向

    • 相机的预览方向   将图像传感器捕获的图像,现实在屏幕上的方向。在默认 情况下,与预想传感器方向一致。在相机API中通过setDisplayOrientation()设置相机预览方向在默认情况下,这个值为0与图像传感器方向一致。
    • 绝大部分安卓手机中图像传感器方向是横向的,且不能改变,所以orientation是90或是270,也就是说,当点击拍照后保存图片的时候,需要对图片做旋转处理,使其为"自然方向"。 (可能存在一些特殊的定制或是能外接摄像头的安卓机,他们的orientation会是0或者180)

    • 通过setDisplayOrientation方法设置预览方向,使预览画面为"自然方向"。前置摄像头在进行角度旋转之前,图像会进行一个水平的镜像翻转,所以用户在看预览图像的时候就像照镜子一样。

          

                                                             Camera内部类

    SiZi                                                                                                                                                                                                         图片大小包含俩个变量:width和height (图片的宽和高)

    Parameters 

             Parameters是相机服务设置,不同的相机可能是不相同的。比如相机所支持的图片大小,对焦模式等等。下面介绍一下这个类中常用的方法

    • getSupportedPreviewSizes()                                                                                                                                                       获得相机支持的预览图片大小,返回值是 List(Sizi)
    • setPreviewSize(int width, int height)                                                                                                                                             设置相机预览的图片大小
    • getSupportedPreviewFormats()                                                                                                                                                   获取相机支持的图片格式
    • setPreviewFormat(int pixel_format)                                                                                                                                              设置图片的预览格式
    • getSupportedPictureSizes()                                                                                                                                                          获取相机支持的采集图片大小(就是拍照后保存的图片大小)
    • setPictureSize(int width, int height)                                                                                                                                                 设置保存的图片的大小
    • getSupportedPictureFormats()                                                                                                                                                      获取相机支持的图片格式
    • setPictureFormat()                                                                                                                                                                   设置相机保存的图片格式                                                             
    • getSupportedFocusModes()                                                                                                                                                         获取相机支持的对焦模式
    • setFocusMode(String value)                                                                                                                                                          设置相机的对焦模式
    • getMaxNumDetectedFaces()                                                                                                                                                        返回相机最大的人脸检测数量  

                                                            PreviewCallback 

          PreviewCallback 是一个抽象接口

    • void onPreviewFrame(byte[] data, Camera camera)
      通过onPreviewFrame方法来获取到相机预览的数据,第一个参数data,就是相机预览到的原始数据。data可以转换图片做人脸检测

                                                             Face

      

    Face类用来描述通过Camera的人脸检测功能检测到的人脸信息

    • rect                                                                                                                                                                                               rect 是一个Rect对象,它所表示的就是检测到的人脸的区域
    • score                                                                                                                                                                                             人脸的可信度(0-100)
    • leftEye                                                                                                                                                                                          左眼位置坐标系
    • rightEye                                                                                                                                                                                         右眼位置坐标系     
    • mouth                                                                                                                                                                                             眼睛位置坐标系     
    •   leftEye       rightEye         mouth    都是 Point 对象  部分手机可能返回来为 null

                                               FaceDetectionListener

    抽象接口开始人脸检测的时候回调

    • onFaceDetection(Face[] faces, Camera camera)
      第一参数代表检测到的人脸,是一个Face数组(画面内可能存在多张人脸)

                                                    Camera类中的方法

    • getNumberOfCameras()
      返回当前设备上可用的摄像头个数
    • open()
      使用当前设备上第一个后置摄像头创建一个Camera对象。如果当前设备没有后置摄像头,则返回值为null
    • open(int cameraId)
      使用传入id所表示的摄像头创建一个Camera对象,如果id所表示的摄像头已经被打开,则会抛出异常

    设备上每一个物理摄像都是有一个id的,id从0开始,到getNumberOfCameras() - 1 结束 

    • getCameraInfo(int cameraId, CameraInfo cameraInfo)
      返回指定id所表示的摄像头的信息
    • setDisplayOrientation(int degrees)
      设置相机预览画面旋转的角度
    • setPreviewDisplay(SurfaceHolder holder)
      设置一个Surface对象用来实时预览
    • setPreviewCallback(PreviewCallback cb)
      设置相机预览数据的回调,参数是一个PreviewCallback对象
    • getParameters()
      返回当前相机的参数信息,返回值是一个Parameters对象
    • setParameters(Parameters params)
      设置当前相机的参数信息
    • startPreview()
      开始预览
      调用此方法之前,如果没有setPreviewDisplay(SurfaceHolder) 或 setPreviewTexture(SurfaceTexture)的话,是没有效果

    • stopPreview()
      停止预览

    • startFaceDetection()
      开始人脸检测
      这个方法必须在开始预览之后调用

    • stopFaceDetection()
      停止人脸检测

    • setFaceDetectionListener(FaceDetectionListener listener)
      设置人脸检测监听回调

    • release()
      释放相机

                                                                                  第一章末尾

    展开全文
  • Android中的Camera相机开发设计示例演示
  • Android相机开发系列

    2021-06-03 06:37:37
    Android Camera Develop Series简介Android相机开发系列文章循序渐进,教你从一个没有任何功能的相机APP开始,逐步完善实现一般相机APP的各种功能,甚至还能拿来做图像处理。系列文章力求简单精炼,以快速上手,理解...
  • 开关相机分为以下几个步骤:申请授权-->选择相机-->打开相机-->关闭相机 1申请授权 在使用相机 API 之前,必须在 AndroidManifest.xml 注册相机权限 android.permission.CAMERA。 静态授权 <...
  • Android相机开发代码

    热门讨论 2013-09-25 22:23:55
    简单的Android相机程序,可实现以下功能: 1、预览 2、对焦拍照保存 3、查看图片,并且能够更新按钮的图像缩略图
  • BitmapFactory时务必要尽快的使用Bitmap.recycle();方法进行内存回收,在java中,一般都很少有内存回收的说法,但偏偏这里出现这方法,说明这方法的重要性,使用了这方法,就没出现过内存溢出了!!@Overridepublic void ...
  • Android 相机开发例程

    2014-03-12 06:47:29
    Android 相机开发例程,带有详细的注释说明和工具函数
  • Android相机开发那些坑

    2018-04-09 16:59:26
    最近我负责开发了一个跟Android相机有关的需求,新功能允许用户使用手机...这篇文章总结了Android相机开发的相关知识、流程,以及容易遇到的坑,希望能帮助今后可能会接触Android相机开发的朋友快速上手,节省时间...
  • android调用相机问题 解决三星相机调用BUG
  • 又由于Android系统自带的WebView被人吐槽过多,所以决定使用腾讯封装的X5内核的WebView,使用和方法上和系统的相差不大。 第一步:在布局中使用WebView。 我们设置一个progressbar用来提示加载进度,我想从用户...
  • Android相机开发

    千次阅读 2018-06-15 15:25:07
    基础相机开发中常用的APIpackage android.hardware.camera2 这个包中包含了主要的相机控制的API,可以用于在你的项目中进行拍照或者录像功能的实现Camera 这个类是早些版本驱动相机的APISurfaceView 用于相机预览的...
  • Android相机开发和遇到的坑
  • Android Camera Develop: touch to focus, touch to metering, double finger touch to zoom概述本篇在(四)的基础上继续对相机APP的功能进行增强。触摸对焦,就是在屏幕上点击某个点,相机就以此点内容进行对焦,...
  • Android 水印相机开发

    2021-06-06 15:28:21
    水印相机是自定义相机的一种,实现方法有很多,我看了很多别人的做的很漂亮,我做的就很普通了,不过总算是实现了拍照加水印的功能。我这边用到了SurfaceView,有人没用这个也做出来...相机功能由android.hardware...
  • Android: Camera2相机开发 知识储备

    千次阅读 2022-04-05 14:11:50
    进行Camera开发主要用到了以下两个类: 1.Camera 2.TexttureView(也可以是SurfaceView) 一、Surface Surfaces是用来处理屏幕显示内容合成器所管理的原始缓存区的工具。它通常由图像缓冲区的消费者来创建(如:...
  • 今天小编就为大家分享一篇浅谈Android 照相机权限的声明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • Android相机开发详解(一)

    千次阅读 2015-02-11 10:55:41
    Android相机开发详解(一) 主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能。
  • Android相机开发实战

    万次阅读 多人点赞 2015-09-07 11:28:03
    开源分享二(Android相机开发实战教程) 上篇博文给大家分享了两个非常实用的项目功能模块,不知道大伙感觉如何?有木有一种臭袜子味扑鼻,酸爽的赶脚!!!贱笑贱笑了~ ~ OK!不扯淡了,言归正传。本文将主要为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,770
精华内容 13,108
关键字:

安卓相机开发