学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题

最近学习安卓拍照部分的知识,其中遇到不少的坑,看视频学习,照着视频里面的代码敲,代码一毛一样,可是我的就是总是出现各种各样的问题,真的是烦~
捣鼓了两三天终于搞好了。

废话不多说。

先看调用系统相机:
先看图:
学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题_第1张图片
学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题_第2张图片学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题_第3张图片
xml布局文件


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/preView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal"
        android:padding="20dp">

        <Button
            android:id="@+id/takephoto"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:padding="20dp"
            android:background="@drawable/takephoto" />
    LinearLayout>
RelativeLayout>

java文件 SystemCameraActivity.java

package com.exercise03.testapp;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;

//调用系统相机

public class SystemCameraActivity extends AppCompatActivity{
    private Button takePhoto;
    private ImageView preView;
    private File capturedPhoto = null;
    private Uri fileUri = null;
    private final int REQUEST_CODE = 1;

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

        //严格模式
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        builder.detectFileUriExposure();

        //绑定控件
        preView = (ImageView)findViewById(R.id.preView);
        takePhoto = (Button)findViewById(R.id.takephoto);

        //设置takePhoto按钮监听事件
        takePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //将文件保存在SD卡中
                File dir = new File(Environment.getExternalStorageDirectory(),"SystemCamera");
                if(!dir.exists()){
                    dir.mkdirs();
                }

                //照片文件名
                String capturePhotoName = System.currentTimeMillis() + ".jpg";
                capturedPhoto = new File(dir,capturePhotoName);
                //判断该文件是否存在
                if(!capturedPhoto.exists()){
                    //创建这个文件
                    try {
                        capturedPhoto.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                //step1:调用系统相机  (隐式 Intent)
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                fileUri = Uri.fromFile(capturedPhoto);
                intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);

                //step2: 启用intent
                startActivityForResult(intent,REQUEST_CODE);

            }
        });

    }

    //step3: 重写方法

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        //将拍照得到的照片添加到ImageView中
        if(requestCode == REQUEST_CODE){
            fileUri = Uri.fromFile(capturedPhoto);
            preView.setImageURI(fileUri);
            Toast.makeText(this, "图片已加载到ImageView中", Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(this, "图片加载失败", Toast.LENGTH_SHORT).show();
        }
    }
}

写调用系统相机的代码中遇到这样的问题

问题1:
之前是使用xml文件的onClick属性调用方法,结果一直显示

 java.lang.IllegalStateException: Could not find method systemCamera(View)
in a parent or ancestor Context for android:onClick attribute defined on
view class android.widget.Button with id 'takephoto' at
 android.view.View$DeclaredOnClickListener.resolveMethod

让后百度得到的结果是可能xml文件的布局嵌套得太深的问题,所以我改成了设置监听的方式调用方法
解决了这个问题

问题2:

android.os.FileUriExposedException:
file:///storage/emulated/0/Android/data/com.yuyh.imgsel/
cache/1486438962645.jpg exposed beyond app through 
ClipData.Item.getUri()

原因

主要是由于在Android 7.0以后,用了Content Uri 替换了原本的File Uri, * 故在targetSdkVersion=24的时候,部分 “Uri.fromFile() “ 方法就不适用了。 * File Uri 与 Content Uri 的区别 - File Uri 对应的是文件本身的存储路径 - Content Uri * 对应的是文件在Content Provider的路径 * 所以在android 7.0 以上,我们就需要将File Uri转换为 Content Uri。

解决方法:在onCreate方法中加入以下代码即可解决

//严格模式
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        builder.detectFileUriExposure();

问题3:
调用系统相机拍的照片无法加载到ImageView中
这个问题很奇怪,我在网上看到if(requestCode == REQUEST_CODE)这个判断语句是这样的if(requestCode == REQUEST_CODE && requestCode == REQUEST_OK),还有看视频教程里也是这样的,但是我把&& requestCode == REQUEST_OK删掉后就可把照片加载到ImageView中了。

==分割线

自定义相机:
先看图
学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题_第4张图片

xml布局文件:


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal"
        android:padding="20dp">

        <Button
            android:id="@+id/takephoto"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:padding="20dp"
            android:background="@drawable/takephoto" />
    LinearLayout>
RelativeLayout>


java文件 CustomCameraActivity.java
看图

package com.exercise03.testapp;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

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

public class CustomCameraActivity extends AppCompatActivity {
    //step1:设置各种所需要的变量
    private Camera camera;                  //定义相机对象
    private boolean isPreview = false;      //定义非预览状态
    private SurfaceView surfaceView;
    private Button takePhoto;
    String photoPath = "/DCIM/Camera/";     //照片文件存储路径
    //这个也是一个变量,只是很长而已
    private SurfaceHolder.Callback SurfaceHolder_Callback = new SurfaceHolder.Callback(){

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            startPreview();     //开始预览
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            stopPreview();      //停止预览
        }
    };


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

        //设置全屏显示
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);


        /*//这个好像没什么用了,因为现在大多数手机都不装SD卡了
        if (!Environment.getExternalStorageState().equals(  //判断手机是否安装SD卡
                Environment.MEDIA_MOUNTED)) {
            Toast.makeText(this, "请安装SD卡!", Toast.LENGTH_SHORT).show(); // 提示安装SD卡
        }
        */


        //step2:
        //获取SurfaceView组件,用于显示相机预览
        surfaceView = (SurfaceView)findViewById(R.id.surfaceView);
        //获取SurfaceHolder对象
        final SurfaceHolder surfaceHolder = surfaceView.getHolder();
        //设置该SurfaceHolder自己不维护缓冲
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(SurfaceHolder_Callback);//刚刚那个很长的变量用在这里了

        //获取Button组件,用于拍照
        takePhoto = (Button)findViewById(R.id.takephoto);
        takePhoto.setOnClickListener(new View.OnClickListener() {//设置按钮监听事件
            @Override
            public void onClick(View v) {
                if(camera != null){
                    camera.takePicture(null,null,Camera_PictureCallback);
                    Toast.makeText(CustomCameraActivity.this, "照片已保存在" + photoPath + "中", Toast.LENGTH_SHORT).show();
                }
            }
        });

    }

    //step3: 实现将照片保存到系统图库中
    final Camera.PictureCallback Camera_PictureCallback = new Camera.PictureCallback(){

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 根据拍照所得的数据创建位图
            Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
            camera.stopPreview();       //停止预览
            isPreview = false;         //设置为非预览状态

            //获取sd卡根目录
            File dir = new File(Environment.getExternalStorageDirectory(),photoPath);
            if(!dir.exists()){      //如果该目录不存在
                dir.mkdirs();       //就创建该目录
            }

            //将获取当前系统时间设置为照片名称
            String fileName = System.currentTimeMillis() + ".jpg";
            //创建文件对象
            File capturedPhoto = new File(dir,fileName);

            try {
                FileOutputStream fileOutputStream = new FileOutputStream(capturedPhoto);
                bitmap.compress(Bitmap.CompressFormat.JPEG,100,fileOutputStream);
                fileOutputStream.flush();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };



    //开始预览,图像显示在SurfaceView中
    public void startPreview(){
        camera = Camera.open();
        isPreview = true;                                //设置为预览状态
        try {
            camera.setPreviewDisplay(surfaceView.getHolder());
            camera.setDisplayOrientation(90);   //让相机旋转90度
            camera.startPreview();
            camera.autoFocus(null);                        //设置自动对焦
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //停止预览
    public void stopPreview(){
        camera.stopPreview();
        camera.release();
        camera = null;
    }


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

        if(camera != null){
            camera.stopPreview();
            camera.release();
        }
    }
}

这个到好像没遇到什么问题。

最后一定得把权限加上,在AndroidManifest.xml文件中加上下面的代码

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">uses-permission>
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />

最后最后,打开APP前先要把相机权限和存储权限打开,不然APP会闪退

学习Android开发:调用系统相机与自定义相机以及学习过程中遇到的问题_第5张图片

测试使用机型:小米8(android 9.0)

你可能感兴趣的:(Android安卓,Android,安卓,相机)