Android相机之MediaStore.ACTION_IMAGE_CAPTURE

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/I_do_can/article/details/72123161

本文主要记录一些零碎的东西

比扣扣上传头像时,可以拍照,需要选取拍照的应用,今天做的事就是提供供选择的拍照应用

使用我们的相机拍照,返回拍照数据

话不多说,看看效果


原理主要是向系统注册 action

给出的只是一个简单的测试代码,实际项目里camera的管理不能像我写的这样

看看实现:

app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.cl.slack.opencamera">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>

            <!-- IMAGE_CAPTURE  返回Bitmap or 图片文件 -->
            <intent-filter>
                <action android:name="android.media.action.IMAGE_CAPTURE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

        </activity>
    </application>

</manifest>
CameraView.java

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

/**
 * Created by slack
 * on 17/5/12 下午6:06
 * 主要的surfaceView,负责展示预览图片,camera的开关
 */

public class CameraView extends SurfaceView implements SurfaceHolder.Callback{

    private SurfaceHolder mHolder = null;

    private Camera mCamera;

    private final int mDegree = 90;

    public CameraView(Context context) {
        this(context,null);
    }

    public CameraView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mHolder = this.getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        try {
            //设置camera预览的角度,因为默认图片是倾斜90度的
            mCamera.setDisplayOrientation(mDegree);
            //设置holder主要是用于surfaceView的图片的实时预览,以及获取图片等功能,可以理解为控制camera的操作..
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            mCamera.release();
            mCamera = null;
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        /**
         * 如果使用正常拍照进行拍照,设置了这个 Rotation, 拍得的图片总是竖直的
         */
        parameters.setRotation(mDegree);
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }

    public void takePicture(PictureCallback callback){
        mCamera.takePicture(null, null, new CameraPictureCallback(callback));
    }

    // 回调用的picture,实现里边的onPictureTaken方法,其中byte[]数组即为照相后获取到的图片信息
    private class CameraPictureCallback implements Camera.PictureCallback {

        private PictureCallback pictureCallback;
        public CameraPictureCallback(PictureCallback callback) {
            pictureCallback = callback;
        }

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Bitmap b = null;
            if(null != data){
                b = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
                mCamera.stopPreview();
            }

            //保存图片到sdcard
            if(null != b)
            {
                if(pictureCallback != null){
                    pictureCallback.onPictureTaken(b);
                }
                //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。
                //图片竟然不能旋转了,故这里要旋转下
//                Bitmap rotaBitmap = getRotateBitmap(b, mDegree);
//                b.recycle();
//                if(pictureCallback != null){
//                    pictureCallback.onPictureTaken(rotaBitmap);
//                }
            }
            //再次进入预览
            mCamera.startPreview();
        }

    };

    private Bitmap getRotateBitmap(Bitmap b, float rotateDegree){
        Matrix matrix = new Matrix();
        matrix.postRotate((float)rotateDegree);
        Bitmap rotaBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, false);
        return rotaBitmap;
    }

    public interface PictureCallback {
        void onPictureTaken(Bitmap bitmap);
    }

}


主要功能代码

ImageCapture.java

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.OutputStream;

/**
 * Created by slack
 * on 17/5/12 下午4:07
 * 外部 调用 无他相机 拍照 返回照片
 * 1.有读写外部文件权限
 */

public class ImageCapture {

    public static final ImageCapture IMAGE_CAPTURE = new ImageCapture();

    private ImageCapture(){}

    public Uri mUri = null;

    public File mFile = null;

    public boolean isEmpty(){
        return mUri == null;
    }

    public boolean updateCaptureAction(Intent intent){
        if (intent.getAction() != null) {
            if (intent.getAction().equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
                try {
                    Uri fileUri = intent.getExtras().getParcelable(MediaStore.EXTRA_OUTPUT);
                    updateUri(fileUri);
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            }
        }
        return true;
    }

    private void updateUri(Uri uri) {
        mUri = uri;
        if(uri != null){
            mFile = new File(uri.getPath());
            // 缓存空间
            if (mFile.getAbsolutePath().equals("/scrapSpace")) {
                mFile = new File(Environment.getExternalStorageDirectory()
                        .getAbsolutePath() + "/mms/scrapSpace/.temp.jpg");
            }
            mFile.mkdirs();
            Log.i("slack","ImageCapture uri:" + uri + " file:" + mFile.getAbsolutePath());
        }
    }

    /**
     * call on main thread
     */
    public void saveBitmapToFile(final Activity activity,final Bitmap bitmap){
        Toast.makeText(activity,"正在生成图片...",Toast.LENGTH_LONG).show();
        new AsyncTask<Void,Void,Void>(){
            @Override
            protected Void doInBackground(Void... params) {
                if (mFile.exists()) {
                    mFile.delete();
                }
                OutputStream out;
                try {
                    out = activity.getContentResolver().openOutputStream(mUri);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 80, out);
                    out.flush();
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    bitmap.recycle();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                activity.setResult(Activity.RESULT_OK);
                activity.finish();
                Log.i("slack","ImageCapture saveImageToAlbum:" + mFile.exists() + " file:" + mFile.getAbsolutePath());
            }
        }.execute();
    }

    public void saveBitmapToFile(final Activity activity,final byte[] data){
        Toast.makeText(activity,"正在生成图片...",Toast.LENGTH_SHORT).show();
        new AsyncTask<Void,Void,Void>(){
            @Override
            protected Void doInBackground(Void... params) {
                if (mFile.exists()) {
                    mFile.delete();
                }
                try {
                    OutputStream out = activity.getContentResolver().openOutputStream(mUri);
                    BufferedOutputStream bufferedOutput = new BufferedOutputStream(out);
                    bufferedOutput.write(data);
                    out.flush();
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                activity.setResult(Activity.RESULT_OK);
                activity.finish();
                Log.i("slack","ImageCapture saveImageToAlbum:" + mFile.exists() + " file:" + mFile.getAbsolutePath());
            }
        }.execute();
    }

    public void clear(){
        mFile = null;
        mUri = null;
    }

}


然后测试的代码:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.cl.slack.opencamera.MainActivity">

    <com.cl.slack.opencamera.CameraView
        android:id="@+id/slack_camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="点击拍照"
        android:onClick="takePhoto"
        android:layout_marginBottom="20dp"
        android:layout_gravity="bottom|center"/>

</FrameLayout>
测试代码:

import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

/**
 * ImageCapture MediaStore.ACTION_IMAGE_CAPTURE
 * created by slack
 * on 17/5/12 下午7:05
 */
public class MainActivity extends AppCompatActivity {

    CameraView mCameraView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 判断是否 image capture
        ImageCapture.IMAGE_CAPTURE.updateCaptureAction(this.getIntent());

        setContentView(R.layout.activity_main);
        mCameraView = (CameraView) findViewById(R.id.slack_camera_view);
    }

    public void takePhoto(View view) {
        mCameraView.takePicture(mPictureCallback);
    }

    private CameraView.PictureCallback mPictureCallback = new CameraView.PictureCallback() {
        @Override
        public void onPictureTaken(Bitmap bitmap) {
            if(ImageCapture.IMAGE_CAPTURE.isEmpty()){
               // do normal things
                Toast.makeText(MainActivity.this,"normal click",Toast.LENGTH_SHORT).show();
            }else {
                ImageCapture.IMAGE_CAPTURE.saveBitmapToFile(MainActivity.this,bitmap);
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ImageCapture.IMAGE_CAPTURE.clear();
    }

}


- - - - - - - - - - - - - -update 2017-06-05 - - - - - - - - - - - - - - 

新增 对 没有指定存储路径的支持,类似调用系统相机拍照,直接返回 bitmap

ImageCapture.java :

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.widget.Toast;

import com.benqu.core.util.D;

import java.io.File;
import java.io.OutputStream;

/**
 * Created by slack
 * on 17/5/12 下午4:07
 * 外部 调用 无他相机 拍照 返回照片
 * 1.有读写外部文件权限
 * 2.需要先初始化 菜单
 * 支持 带输出路径 和 不带输出路径的调用
 * 1. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 启动系统相机
 *    startActivityForResult(intent, REQUEST_CAMERA_1);
 * 2. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 启动系统相机
 *    Uri photoUri = Uri.fromFile(new File(mFilePath)); // 传递路径
 *    intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);// 更改系统默认存储路径
 *    startActivityForResult(intent, REQUEST_CAMERA_2);
 */

public class ImageCapture {

    public static final ImageCapture IMAGE_CAPTURE = new ImageCapture();

    private ImageCapture(){}

    public Uri mUri = null;

    public File mFile = null;

    private boolean mNeedImageCapture = false;

    public boolean isEmpty(){
        return !mNeedImageCapture;
    }

    public void updateCaptureAction(Intent intent){
        if (intent.getAction() != null) {
            if (intent.getAction().equals(MediaStore.ACTION_IMAGE_CAPTURE)) {
                mNeedImageCapture = true;
                Uri fileUri = null;
                Bundle bundle = intent.getExtras();
                if(bundle != null) {
                    fileUri = bundle.getParcelable(MediaStore.EXTRA_OUTPUT);
                }
                updateUri(fileUri);
            }
        }
    }

    private void updateUri(Uri uri) {
        mUri = uri;
        if(uri != null){
            mFile = new File(uri.getPath());
            // 缓存空间
            if (mFile.getAbsolutePath().equals("/scrapSpace")) {
                mFile = new File(Environment.getExternalStorageDirectory()
                        .getAbsolutePath() + "/mms/scrapSpace/.temp.jpg");
            }
            D.i("slack", "ImageCapture uri:" + uri + " file mkdirs " +
                    (mFile.mkdirs() ? "success" : "fail") + ", file path:" + mFile.getAbsolutePath());
        }
    }

    /**
     * call on main thread
     */
    public void onObtainBitmap(final Activity activity, final Bitmap bitmap){
        Toast.makeText(activity,"正在生成图片...",Toast.LENGTH_LONG).show();
        if(mUri != null) {
            new AsyncTask<Void, Void, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    if (mFile.exists()) {
                        mFile.delete();
                    }
                    OutputStream out;
                    try {
                        out = activity.getContentResolver().openOutputStream(mUri);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                        out.flush();
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        bitmap.recycle();
                    }
                    return null;
                }

                @Override
                protected void onPostExecute(Void aVoid) {
                    activity.setResult(Activity.RESULT_OK);
                    activity.finish();
                    D.i("slack", "ImageCapture saveImageToAlbum file exists:" + mFile.exists() + " file:" + mFile.getAbsolutePath());
                }
            }.execute();
        } else {
            // 此处只返回缩略图 Intent 传输数据 < 1M
            Intent intent = new Intent();
            intent.setAction("inline-data");
            intent.putExtra("data", reSampleBitmap(bitmap));
            activity.setResult(Activity.RESULT_OK, intent);
            activity.finish();
        }
    }

    /**
     * 暂定拍照数据 1/16   TODO 修改这个大小
     * @param bitmap
     * @return
     */
    private Bitmap reSampleBitmap(Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.setScale(0.25f, 0.25f);
        Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);
        D.i("slack", "压缩后图片的大小" + (result.getByteCount() / 1024f / 1024f)
                + "M宽度为" + result.getWidth() + "高度为" + result.getHeight());
        return result;
    }

    public void clear(){
        mNeedImageCapture = false;
        mFile = null;
        mUri = null;
    }

}
测试代码

// 拍照并显示图片
    private void openCamera_1() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 启动系统相机
        startActivityForResult(intent, REQUEST_CAMERA_1);
    }

    // 拍照后存储并显示图片
    private void openCamera_2() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 启动系统相机
        Uri photoUri = Uri.fromFile(new File(mFilePath)); // 传递路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);// 更改系统默认存储路径
        startActivityForResult(intent, REQUEST_CAMERA_2);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) { // 如果返回数据
            if (requestCode == REQUEST_CAMERA_1 && data != null) { // 判断请求码是否为REQUEST_CAMERA,如果是代表是这个页面传过去的,需要进行获取
                Bundle bundle = data.getExtras(); // 从data中取出传递回来缩略图的信息,图片质量差,适合传递小图片
                Bitmap bitmap = (Bitmap) bundle.get("data"); // 将data中的信息流解析为Bitmap类型
                ivShowPicture.setImageBitmap(bitmap);// 显示图片
            } else if (requestCode == REQUEST_CAMERA_2) {
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(mFilePath); // 根据路径获取数据
                    Bitmap bitmap = BitmapFactory.decodeStream(fis);
                    ivShowPicture.setImageBitmap(bitmap);// 显示图片
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        fis.close();// 关闭流
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }





猜你喜欢

转载自blog.csdn.net/I_do_can/article/details/72123161