使用系统相机

android中使用系统相机是很方便的,单这仅仅是简单的使用而已,并不能获得什么特殊的效果。


要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下

 <intent-filter>
                <action android:name="android.intent.action.IMAGE_CAPTURE" />

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

action的作用就是声明action的类型,便于Intent的使用,category的作用就是注册,没有它。相关操作将不起作用。

一种方式是简单粗暴的实现,如下

Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, REQ_1);
//然后在 onActivityResult方法中实现数据的获取,此处是展示在了一个ImageView上
if(resultCode==RESULT_OK){
            if(requestCode==REQ_1){
                Bundle bundle=data.getExtras();
                Bitmap bitmap=(Bitmap) bundle.get("data");
                imageView.setImageBitmap(bitmap);
                }

小总结:这样的好处是简单快捷,但是在现在的android智能机中,好多相片都是很大的,这里获得的仅仅是一个缩略图罢了


另外一种方式是稍微温婉一点了,而且效果也更好一点,好处就在于它是先将照片信息存储到本地一个临时文件中,然后让ImageView去相关路径下进行读取,这样就可以获得清晰度很高的图片了。如下

/*
     * 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图
     * 这样的好处就是可以对大容量的照片进行便捷的准确的操作
     */
    public void onStartCarema2(View view){
        Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //见你给你路径传递回需要的处理方法中
        Uri uri=Uri.fromFile(new File(myFilePath));
        //设置文件的输出路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        startActivityForResult(intent, REQ_2);
    }
//然后在onActivityResult方法中进行相关的处理就可以了
else if(requestCode==REQ_2){
                FileInputStream fis=null;
                try {
                    fis=new FileInputStream(myFilePath);
                    Bitmap bitmap=BitmapFactory.decodeStream(fis);
                    imageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally{
                    try {
                        fis.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
//记得最后一定要关闭相关的流操作。否则会引起相关的异常的。

开发自定义的相机

由于开发自定义的相机要进行相关的权限的生命,所以一定不要忘记在清单文件中做相关的处理,如下

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

然后有以下几个步骤:

  1. 创建Camera,并完成初始化Camera,开始预览,释放资源三个方法
  2. 与Activity的SurfaceView进行绑定。
  3. 在系统的onPause(),onResume()方法中进行相关状态设置
  4. 对Camera进行参数设置,作用就是对照片类型和状态进行相关的设置
  5. 将拍得的照片进行展示,一般会新开一个Activity,用ImageView进行承载,我们还可以在此Activity上添加TextView,实现水印效果等其他的美化操作
  6. 另外,如果想加入自动聚焦的功能,就可以在SurfaceView上添加onClickListener(),对屏幕进行侦听,调用myCamera.autoFocus(null);方法即可

以上就是整个思路


接下来就是使用系统Camera的代码展示

(可以直接copy相关代码块,添加到你的应用中去,实现Camera这一功能。)

首先是MainActivity

  • 布局
<LinearLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/startCarema"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:text="StartCarema"
        android:onClick="onStartCarema"
        />
    <Button
        android:id="@+id/startCarema2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:text="StartCarema2"
        android:onClick="onStartCarema2"
        />
    <Button
        android:id="@+id/customCarema"
       android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:text="CustomCarema"
        android:onClick="onCustomCarema"
        />

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

        />

</LinearLayout>
  • 代码
package com.example.camerademo;

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

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {
    //为下面的获取请求所用
    private static int REQ_1=1;
    private static int REQ_2=2;

    Button btn_startCareme,btn_startCarema2,btn_customCarema;
    ImageView imageView;

    //定义照片存储的路径
    private String myFilePath;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_startCareme=(Button) findViewById(R.id.startCarema);
        btn_startCarema2=(Button) findViewById(R.id.startCarema2);
        btn_customCarema=(Button) findViewById(R.id.customCarema);
        imageView=(ImageView) findViewById(R.id.imageview);

        //初始化不同手机的SD卡的路径
        myFilePath=Environment.getExternalStorageDirectory().getPath();
        myFilePath=myFilePath+"/"+"temperature.png";
    }

    public void onCustomCarema(View view){
        Intent intent=new Intent(this,CustomCarema.class);
        startActivity(intent);
    }

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

    /*
     * 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图
     * 这样的好处就是可以对大容量的照片进行便捷的准确的操作
     */
    public void onStartCarema2(View view){
        Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //见你给你路径传递回需要的处理方法中
        Uri uri=Uri.fromFile(new File(myFilePath));
        //设置文件的输出路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        startActivityForResult(intent, REQ_2);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK){
            if(requestCode==REQ_1){
                Bundle bundle=data.getExtras();
                Bitmap bitmap=(Bitmap) bundle.get("data");
                imageView.setImageBitmap(bitmap);
            }else if(requestCode==REQ_2){
                FileInputStream fis=null;
                try {
                    fis=new FileInputStream(myFilePath);
                    Bitmap bitmap=BitmapFactory.decodeStream(fis);
                    imageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }finally{
                    try {
                        fis.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

接下来是自定义相机的代码

  • 主界面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/capture"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:text="Capture"
        android:onClick="onCapture"
        />

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

        />

</LinearLayout>
  • ResultActivity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Capture Result"
        android:textSize="28dp"
        android:textColor="#BFAACD"
        android:gravity="center"
        />
        <ImageView
            android:id="@+id/picture"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="center"
            />

</LinearLayout>
  • 代码

    首先是CustomCamera类,
package com.example.camerademo;

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

import android.app.Activity;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

@SuppressWarnings("unused")
public class CustomCarema extends Activity implements SurfaceHolder.Callback{

    private Camera myCamera;

    private SurfaceView preview;
    private SurfaceHolder myHolder;   //myHolder勇于展现surfaceView的图像

    private Camera.PictureCallback myPictureCallBack=new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera arg1) {
            //将拍照得到的数据信息存储到本地
            File tempFile=new File("/sdcard/temp.png");
            try {
                FileOutputStream fos=new FileOutputStream(tempFile);
                fos.write(data);
                fos.close();
                //然后将这个照片的数据信息传送给要进行展示的Activity即可
                Intent intent=new Intent(CustomCarema.this,ResultActivity.class);
                intent.putExtra("PicturePath", tempFile.getAbsolutePath());
                startActivity(intent);
                //拍照结束之后销毁当前的Activity,进入到图片展示界面
                CustomCarema.this.finish();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.customcarema);
        preview=(SurfaceView) findViewById(R.id.preview);
        myHolder=preview.getHolder();
        myHolder.addCallback(this);

        //实现点击屏幕自动聚焦的功能,此处并不需要拍照,故只是聚焦
        preview.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                myCamera.autoFocus(null);
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(myCamera==null){
            myCamera=getCamera();
            if(myHolder != null ){
                setStartPreview(myCamera, myHolder);
            }
        }
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        releaseCamera();
    }

    /**
     * 释放相机的资源
     */
    private void releaseCamera(){
        if(myCamera !=null ){
            myCamera.setPreviewCallback(null);
            myCamera.stopPreview();
            myCamera.release();
            myCamera=null;
        }
    }

    /**
     * 拍照的一些参数设置,点击此按钮之后会触发拍照的会掉,进而实现拍照的效果
     * @param view
     */
    public void onCapture(View view){
        Camera.Parameters parameters=myCamera.getParameters();
        //设置照片的类型
        parameters.setPictureFormat(ImageFormat.JPEG);
        parameters.setPictureSize(800, 600);
        //设置为自动聚焦
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        //设置为自动聚焦是不够的,因为我们先得到的是最为清晰的图片,所以要在聚焦成功的时候才进行拍照
        myCamera.autoFocus(new Camera.AutoFocusCallback() {

            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                // TODO Auto-generated method stub
                if(success){
                    myCamera.takePicture(null, null, myPictureCallBack);
                }
            }
        });
    }

    /**
     * 获取系统的一个Camera对象
     */
    private Camera getCamera(){
        Camera camera=null;
        try{
            camera=Camera.open();
        }catch(Exception e){
            e.printStackTrace();
        }

        return camera;
    }

    /**
     * 开始预览相机的内容,其实就是讲surfaceHolder与之绑定
     */
    private void setStartPreview(Camera camera,SurfaceHolder holder){
        //直接调用系统方式绑定预览
        try {
            camera.setPreviewDisplay(holder);
            //由于系统默认使用横屏预览,,所以要进行设置
            camera.setDisplayOrientation(90);
            camera.startPreview();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub
        myCamera.stopPreview();
        setStartPreview(myCamera, myHolder);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        setStartPreview(myCamera, myHolder);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        releaseCamera();
    }

}

然后是结果界面代码:

package com.example.camerademo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.widget.ImageView;

public class ResultActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.resultactivity);
        String path=getIntent().getStringExtra("PicturePath");
        ImageView imageview=(ImageView) findViewById(R.id.picture);
        //由于这样稚嫩获得横屏,所以我们要使用流的形式来转换
//      Bitmap bitmap=BitmapFactory.decodeFile(path);
//      imageview.setImageBitmap(bitmap);
        FileInputStream fis;
        try {
            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) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

以上代码中已经做了下关的代码注释


总结:

//写这篇博客的目的一方面是为了今后复习时方便一点,毕竟思路在此刻是清晰的,过几天就有可能忘记了。另一方面若能帮到在这方面有欠缺的小伙伴们的话,那是更好的了。最后尤其要感谢的是Imooc中eclipse_xu 老师,我就是看着他的视频来敲得代码。

Android实现自定义的相机的更多相关文章

  1. Android之运行时相机权限和联系人权限获取

    原文:Android之运行时相机权限和联系人权限获取 本文链接:http://blog.csdn.net/qq_16628781/article/details/61623502 Android之运行 ...

  2. Android RatingBar 自定义样式

    Android RatingBar 自定义样式 1.先定义Style: <style name="RadingStyle" parent="@android:sty ...

  3. Android实现自定义带文字和图片的Button

    Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就 ...

  4. Android Studio 自定义debug签名文件keystore

    Android Studio 自定义debug签名文件keystore

  5. Android读取自定义View属性

    Android读取自定义View属性 attrs.xml : <?xml version="1.0" encoding="utf-8"?> < ...

  6. Android之自定义画图文字动画

    结构: BaseView: package com.caiduping.canvas; import android.content.Context; import android.graphics. ...

  7. Android 三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现

    android三档自定义滑动开关,禁止点击功能的实现,普通开关网上有很多例子,三档滑动开关的则找了整天都没有相关例子,开始用普通开关的源码修改了自己实现了一个类,但效果不如人意,各种边界情况的算法很难 ...

  8. Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View

    一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...

  9. Android Toast 自定义

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

随机推荐

  1. AleNet模型笔记

    谁创造了AlexNet? AlexNet是有Hinton大神的弟子Alex Krizhevsky提出的深度卷积神经网络.它可视为LeNet的更深更宽的版本. AlexNet主要用到的技术 成功使用Re ...

  2. Microsoft Visual Studio 2017 编译最新版 libuv 1.x

    步骤很简单 1 下载最新版的 libuv(地址:https://github.com/libuv 2 安装Git,Python 2.7 ,cmake(这里使用的是 3.11.0-win64-x64 版 ...

  3. c++ 深入理解数组

    阅读前提:你得知道啥是数组. 本文需要弄清楚的问题如下: 1,数组作为函数参数,传入的是值,还是地址? 2,数组作为函数参数,数组的长度能否确定? 解决如下 1,数组作为函数参数,传入的是地址.因为数 ...

  4. 关于ubuntu14.04LTS 64位 播放优酷视频

    起因:chrome无法播放优酷视频,然后换firefox发现居然没有装flash 插件. 解释:关于chrome在网上看到了不少说法,说chrome新版本的不支持adobe flash之类的,但是这些 ...

  5. python学习之路网络编程篇(第五篇)

    paramiko简介 paramiko 是基于Python实现的SSH2远程安装连接,支持认证及秘钥方式.可以实现远程命令执行.文件传输.中间SSH代理等功能. paramiko安装 #!/bin/b ...

  6. python学习之路网络编程篇(第四篇)- 续

    Memcache简介 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速 ...

  7. 进程间通信——XSI IPC之消息队列

    进程间通信XSI IPC有3种:消息队列.共享内存.信号量.它们之间有很多相似之处,但也有各自的特殊的地方.消息队列作为其中比较简单的一种,它会有些什么东西呢,来一起探讨探讨.. 消息队列结构 消息队 ...

  8. 【机器学习】从SVM到SVR

    注:最近在工作中,高频率的接触到了SVM模型,而且还有使用SVM模型做回归的情况,即SVR.另外考虑到自己从第一次知道这个模型到现在也差不多两年时间了,从最开始的腾云驾雾到现在有了一点直观的认识,花费 ...

  9. 记一次MySQL删库的数据恢复

    昨天因为不可描述的原因,数据库直接被 drop database删除.在第一时间停止数据库服务和Web服务,备份MySQL数据目录下的所有文件之后,开始走上数据恢复之路. 第一次干这种事,各种不得法. ...

  10. Android的Ui层次

    UI 概览 Android 应用中的所有用户界面元素都是使用 View 和 ViewGroup 对象构建而成.View 对象用于在屏幕上绘制可供用户交互的内容.ViewGroup 对象用于储存其他 V ...