Android 摄像头

在APP中使用Camera的两种方式

  1. 调用系统相机,或者是具有相机功能的应用
  2. 自定义相机

1. 调用系统相机

  • 1)隐式调用系统的相机
    XML代码:
    在这里插入图片描述
    Activity代码:
    在这里插入图片描述
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
  • 2)让Activity可以作为其他程序可调用的拍照程序
    配置Manifest.xml文件
    在这里插入图片描述
<intent-filter>
   <action android:name="android.media.action.IMAGE_CAPTURE" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

在这里插入图片描述

  • 3)拍照后返回图片( 返回缩略图 和 返回原图 )
    XML布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mytest.MainActivity">
    
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="StartCamera"
        android:text="调用系统拍照" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>

Activity代码:

public class MainActivity extends AppCompatActivity {

    private static  int REQ_1 = 1;
    private ImageView mInageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mInageView = (ImageView) findViewById(R.id.imageView);
    }

    public void StartCamera(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent,REQ_1);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK){
            if(requestCode == REQ_1){
                Bundle bundle = data.getExtras();
                //拍照使用系统自带的相机
				//可能引起拍照完返回调用onActivityResult()时intent携带的数据过大,android已经将data压缩,返回的是图片的缩略图。
                Bitmap bitmap = (Bitmap) bundle.get("data");
                mInageView.setImageBitmap(bitmap);
            }
        }
    }
}

但是:通过调用系统相机拍照获取的图像是缩略图,像素比较低(图片模糊),防止内存溢出。

解决方法:采用另外一种方案(文件路径读取)
XML布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mytest.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="StartCamera"
        android:text="调用系统拍照返回缩略图" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="StartCamera2"
        android:text="调用系统拍照返回原图" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>

Activity代码:

public class MainActivity extends AppCompatActivity {

    private static  int REQ_1 = 1;
    private static  int REQ_2 = 2;
    private ImageView mInageView;
    private String mFilePath;

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

        mInageView = (ImageView) findViewById(R.id.imageView);
        // 需要添加SDCard的读取权限
        mFilePath = Environment.getExternalStorageDirectory().getPath();
        mFilePath = mFilePath + "/" + "temp.png";
    }

    //返回缩略图
    public void StartCamera(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent,REQ_1);
    }
    //返回原图
    public void StartCamera2(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 注意:使用的是 android.net.Uri;
        Uri photoUri = Uri.fromFile(new File(mFilePath));
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
        startActivityForResult(intent,REQ_2);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK){
            if(requestCode == REQ_1){
                Bundle bundle = data.getExtras();
                Bitmap bitmap = (Bitmap) bundle.get("data");
                mInageView.setImageBitmap(bitmap);
            }else if(requestCode == REQ_2){
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(mFilePath);
                    Bitmap bitmap = BitmapFactory.decodeStream(fis);
                    mInageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    try {
                        fis.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }
        }
    }
}

manifest配置文件代码:

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

2. 自定义相机(综合案例)

XML界面布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mytest.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="StartCamera"
        android:text="调用系统拍照返回缩略图" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="StartCamera2"
        android:text="调用系统拍照返回原图" />
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="CustomCamera"
        android:text="自定义相机" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>

MainActivity代码:

public class MainActivity extends AppCompatActivity {

    private static  int REQ_1 = 1;
    private static  int REQ_2 = 2;
    private ImageView mInageView;
    private String mFilePath;

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

        mInageView = (ImageView) findViewById(R.id.imageView);
        // 需要添加SDCard的读取权限
        mFilePath = Environment.getExternalStorageDirectory().getPath();
        mFilePath = mFilePath + "/" + "temp.png";
    }

    //返回缩略图
    public void StartCamera(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent,REQ_1);
    }
    //返回原图
    public void StartCamera2(View view){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 注意:使用的是 android.net.Uri;
        Uri photoUri = Uri.fromFile(new File(mFilePath));
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
        startActivityForResult(intent,REQ_2);
    }
    //自定义相机
    public void CustomCamera(View view){
        Intent intent = new Intent(MainActivity.this, CustomCameraActivity.class);
        // 注意:使用的是 android.net.Uri;
        Uri photoUri = Uri.fromFile(new File(mFilePath));
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
        startActivityForResult(intent,REQ_2);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK){
            if(requestCode == REQ_1){
                Bundle bundle = data.getExtras();
                Bitmap bitmap = (Bitmap) bundle.get("data");
                mInageView.setImageBitmap(bitmap);
            }else if(requestCode == REQ_2){
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(mFilePath);
                    Bitmap bitmap = BitmapFactory.decodeStream(fis);
                    mInageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    try {
                        fis.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }
        }
    }
}

自定义相机布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mytest.CustomCameraActivity">

    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Capture"
        android:onClick="capture"/>

    <SurfaceView
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

CustomCameraActivity代码:

public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback{

    private Camera mCamera;
    private SurfaceView mPreview;
    private SurfaceHolder mHolder;

    //实现回调方法
    private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 参数data存放的是完整的图片数据,不是缩略图
            File tempFile = new File("/sdcard/temp.png");
            try {
                FileOutputStream fos = new FileOutputStream(tempFile);
                fos.write(data);
                fos.close();
                
                //实行页面跳转,展示拍照结果
                Intent intent = new Intent(CustomCameraActivity.this, Result.class);
                intent.putExtra("picPath",tempFile.getAbsolutePath());
                startActivity(intent);
                CustomCameraActivity.this.finish();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };

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

        mPreview = (SurfaceView) findViewById(R.id.preview);
        mHolder = mPreview.getHolder();
        mHolder.addCallback(this);

        //点击SurfaceView自动对焦
        mPreview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.autoFocus(null);
            }
        });
    }

    public void capture(View view) {
        //设置拍照参数
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPictureFormat(ImageFormat.JPEG);
        parameters.setPreviewSize(800, 400);//预览大小
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);//自动对焦
        mCamera.autoFocus(new Camera.AutoFocusCallback() { //获取对清晰的对焦照片
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if(success){ //如果对焦成功
                    Toast.makeText(getApplicationContext(),"对焦成功",Toast.LENGTH_SHORT).show();
                    mCamera.takePicture(null, null, mPictureCallback);
                }else{
                    Toast.makeText(getApplicationContext(),"对焦失败",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    /**
     * 第一步:创建三个方法
     */
    //获取Camera对象,注意Camera包不要导错
    private Camera getCamera() {
        //由于是自定义相机,不是系统i相机,需要添加相机权限
        Camera camera;
        try {
            camera = Camera.open();
        } catch (Exception e) {
            camera = null;
            e.printStackTrace();
        }
        return camera;
    }

    //开始预览相机内容(将相机与SurfaceView进行绑定)
    private void setStartPreview(Camera camera, SurfaceHolder holder) {
        try {
            camera.setPreviewDisplay(holder);
            //将系统Camera预览角度进行调整
            camera.setDisplayOrientation(90);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //释放相机资源 并且将 相机 与 SurfaceView 解除绑定
    private void releaseCamera() {
        if(mCamera != null){
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();;
            mCamera = null;
        }
    }

    /**
     * 第二步:将这三个方法与Activity的生命周期绑定
     */
    @Override
    protected void onResume() {
        super.onResume();
        if(mCamera == null){
            mCamera = getCamera();
            if(mHolder != null){
               setStartPreview(mCamera,mHolder);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();

    }


    /**
     *  第三步:实现 implements SurfaceHolder.Callback 的3个方法
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        setStartPreview(mCamera,mHolder);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mCamera.stopPreview();
        setStartPreview(mCamera, mHolder);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }
}

展示结果的布局界面:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.mytest.Result">
    
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Capture Result"
        android:textSize="30sp"/>

    <ImageView
        android:id="@+id/pic"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="center"
        app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>

Result代码

public class Result extends AppCompatActivity {

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

        String path = getIntent().getStringExtra("picPath");
        ImageView imageView = (ImageView) findViewById(R.id.pic);

        try {
            FileInputStream fis = new FileInputStream(path);
            Bitmap bitmap = BitmapFactory.decodeStream(fis);
            Matrix matrix = new Matrix();//定义一个矩阵
            matrix.setRotate(90);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            imageView.setImageBitmap(bitmap);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

//        Bitmap bitmap = BitmapFactory.decodeFile(path);
//        imageView.setImageBitmap(bitmap);
    }

由于是自定义的相机,需要添加权限
manifest.xml添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值