安卓多媒体API——摄影与视频录制Camera

现在手机动不动就能拍月亮,拍黑洞,拍太阳。而,且,它,们,都,是,安,卓,机。

哈哈,这篇文章关于安卓和摄像头的那些事。

归档到多媒体。


Camera

概述

官方都只给了这么一段简单的话,那我好像也多说不出啥。

反正大概就是“我对摄像头的支持很好,提供了很多简单的API给你用”这种感觉。

?是API文档的传送门:

Android provides full access to the device camera hardware so you can build a wide range of camera or vision-based apps. Or if you just need a way for the user to capture a photo, you can simply request an existing camera app to capture a photo and return it to you.

https://developer.android.google.cn/training/camera

Android框架支持通过Camera APlCamera intent来抓取图像和视频

  • Camera此类是控制设备相机的主要API,此类用于在创建相机应用时获取图片和视频。
  • SurfaceView此类为用户提供camera的实时图像预览 。
  • MediaRecorder此类用于从camera录制视频。
  • Intent  一个MediaStore.ACTION IMAGE CAPTURE或MediaStore.ACTION_VIDEO_CAPTURE的intent,可以使用它来抓取图像或视频,而不用操作Camera对象。

权限

CameraPermission

你的应用必须请求使用设备相机的取限

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

CameraFeatures

你的应用必须也要声明要使用的相机特性:

<uses-feature android:name="android.hardware.Camera"/>

如果你的应用要使用相机或相机的一些特性,但又不是必须的,你应该在manifest中指定这些需求,但把android:required属性置为false

<uses-feature android:name="android.hardware.Camera" android:required="false"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

AudioRecording Permission

在使用视频捕获设备来录制音频时,你的应用必须请求音频捕获权限

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

使用现有的相机

一个不用写代码来获取图片和视频的快速方法是使用intent来调用现有的Android camera应用。

一个camera intent调用现存的相机应用抓取图片或视频剪辑然启返回的你的应用。

调用一个相机intent,主要有以下步骤:

  • 组建一个相机Intent-创建一个请求图片或视频的Intent,使用以下intent类型中的一个:
  1. MediaStore.ACTION IMAGE CAPTURE:从已存在的相机应用中请求一个图片。
  2. MediaStore.ACTION-VIDEO-CAPTURE:从已存在的相机应用中请求一个视频。
  • 启动这个相机Intent,使用startActivityForResult()方法来执行相机intent,在你启动intent后,相机应用的界面会出现在设备屏幕上,然后用户就可以用它来获取图片或视频
  • 接收Intent结果,在你的应用中设置一个onActivityResult(方法来接收从相机intent来的回调和数据,当用户获取了一个图或视频之后(或取消了操作),系统就会调用此方法。

图像获取Intent

使用相机intent获取图像是使用最少代码获取图像的捷运。

一个图像获取intent包含以下额外信息:

MediaStore.EXTRA-OUTPUT——此设置需要一个Uri对象,这个对象指定了一个保存图像的路径和文件名,此设置是可选的,但是强烈建议使用之。如果你没有指定此值,相机应用就会把图像以默认的名字保存到默认的位置。:

private static final int CAPTURE IMAGE_ACTIVITY REQUEST CODE _100;
private Uri fileUri;
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedinstanceState);setContentView(R.layout.main);

    //创建一个获取图像的
    IntentIntent intent = new Intent(MediaStore.ACTION IMAGE CAPTURE);
    //创建一个文件来保存图
    fileUri = getoutputMediafileUri(MEDIA TYPE-IMAGE); 
    //设置图像文件名 
    intent.putExtra(MediaStore.EXTRA OUTPUT, fileUril;
    //开始图像获取
    IntentstartActivityForResult(intent, CAPTURE IMAGE ACTIVITY REQUEST CODE);
}
    public static final int MEDIA_TYPE_IMAGE = 1, MEDIA_TYPE_VIDEO = 2;

    private static Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    private static File getOutputMediaFile(lint type) {
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");
        if (!mediaStorageDir.exists() {
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile = null;
        if (type == MEDIA_TYPE_IMAGE) {
            KmediaFile = new File(mediaStorageDir.getPath() + File.separator + IMG_ + timeStamp + ".jpg");
        } else if (type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + VID + timlstamp + ".mp4" );
        } else {
            return null;
        }
        return mediaFile;
    }
  • 当startActivityForResult()方法被执行,看到一个相机应用的界面
  • 当用户获取了一个图像(或取消了操作),用户界面返回到你的应用,
  • 你必须拦截onActivityResult()方法来接收intent的结果然后再继续执行你的应用。

 拍照实现

关于FileUriExposedException异常可以参考?

https://blog.csdn.net/nishigesb123/article/details/89514737

需要的权限见上文权限部分内容。


源码:

package com.example.a4_25camera;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
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.os.Bundle;
import android.view.View;

import java.io.File;

public class MainActivity extends AppCompatActivity {

    //图片类型
    private static final int MEDIA_TYPE_IMAGE = 1;
    //视频类型
    private static final int MEDIA_TYPE_VIDEO = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }
    }

    //拍照
    public void photo(View v) {
        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
        startActivityForResult(intent, MEDIA_TYPE_IMAGE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (resultCode) {
            case RESULT_OK:
                if (MEDIA_TYPE_IMAGE == requestCode) {
                    System.out.println(file);
                } else if (MEDIA_TYPE_VIDEO == requestCode) {
                    ;
                }
                break;
        }
    }

    //临时先定义一下
    File file = null;
    //参数为类型
    private Uri getOutputMediaFileUri(int type) {
        file = getOutputMediaFile(type);
        return Uri.fromFile(file);
    }

    //获取File
    private File getOutputMediaFile(int type) {
        File file = null;
        //定义目录,两种类型目录应该不一样
        String rootPath = null;
        switch (type) {
            //如果是图片
            case MEDIA_TYPE_IMAGE:
                rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
                file = new File(rootPath + File.separator + System.currentTimeMillis() + ".jpg");
                break;
            //如果是视频
            case MEDIA_TYPE_VIDEO:
                rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath();
                file = new File(rootPath + File.separator + System.currentTimeMillis() + ".mp4");

                break;
        }
        return file;
    }


}

测试效果:

 

视频获取intent

使用相机intent获取视频是使用最少代码使得你的应用获取视频的捷径。
一个视频获取intent可以包含以下额外信息:

  1.  MediaStore.EXTRA_OUTPUT:此设置需要一个保存视频的路径和文件名的Uri。此设置是可选的但强烈推荐,如果你不指定此值,相机应用就杷请求到的图像以默认的文件名保存到默认的文件夹下,这些信息保存在返回的intent的Intent.getData()字段中。
  2. MediaStore.EXTRA_ VIDEO_QUALITY:此值在最低质量最小文件R寸时是0,在最高质量最大文件尺寸时是1。
  3. MediaStore. EXTRA_ DURATION_LIMIT:此值设置获取视频的长度,以秒为单位。
  4. MediaStore.EXTRA_SIZE_ LIMIT:此值设置获取视频文件的大小,以字节为单位。
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE_200;
private Uri fileUri;
@Override
public void onCreate(Bundle savedinstanceState) { 
    super.onCreate(savedinstanceState); 
    setContentView(R.layout.main);
    Intent intent = new Intent(MediaStore_ACTION_VIDEO_CAPTURE);
    fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
    startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}

 

视频录制实现

接之前案例源码的基础上进行修改。

package com.example.a4_25camera;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
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.os.Bundle;
import android.view.View;

import java.io.File;

public class MainActivity extends AppCompatActivity {

    //图片类型
    private static final int MEDIA_TYPE_IMAGE = 1;
    //视频类型
    private static final int MEDIA_TYPE_VIDEO = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());
        }
    }

    //拍照
    public void photo(View v) {
        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
        startActivityForResult(intent, MEDIA_TYPE_IMAGE);
    }

    //录屏
    public void video(View v) {
        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, getOutputMediaFileUri(MEDIA_TYPE_VIDEO));
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
        startActivityForResult(intent, MEDIA_TYPE_VIDEO);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (resultCode) {
            case RESULT_OK:
                if (MEDIA_TYPE_IMAGE == requestCode) {
                    System.out.println(file);
                } else if (MEDIA_TYPE_VIDEO == requestCode) {
                    System.out.println(file);
                    System.out.println(data.getData());
                }
                break;
        }
    }

    //临时先定义一下
    File file = null;

    //参数为类型
    private Uri getOutputMediaFileUri(int type) {
        file = getOutputMediaFile(type);
        return Uri.fromFile(file);
    }

    //获取File
    private File getOutputMediaFile(int type) {
        File file = null;
        //定义目录,两种类型目录应该不一样
        String rootPath = null;
        switch (type) {
            //如果是图片
            case MEDIA_TYPE_IMAGE:
                rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
                file = new File(rootPath + File.separator + System.currentTimeMillis() + ".jpg");
                break;
            //如果是视频
            case MEDIA_TYPE_VIDEO:
                rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath();
                file = new File(rootPath + File.separator + System.currentTimeMillis() + ".mp4");

                break;
        }
        return file;
    }


}

 

效果如?

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云无心鸟知还

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值