Android基础入门教程——9.3 使用Camera拍照

Android基础入门教程——9.3 使用Camera拍照

标签(空格分隔): Android基础入门教程


本节引言

本节给大家带来的是Android中Camera的使用,简单点说就是拍照咯,无非两种,
1.调用系统自带相机拍照,然后获取拍照后的图片
2.要么自己写个拍照页面
本节我们来写两个简单的例子体验下上面的这两种情况~


1.调用系统自带Carema

我们只需下面一席话语,即可调用系统相机,相机拍照后会返回一个intent给onActivityResult。
intent的extra部分包含一个编码过的Bitmap~

Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(it,Activity.DEFAULT_KEYS_DIALER);

//重写onActivityResult方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == Activity.RESULT_OK){
            Bundle bundle = data.getExtras();
            Bitmap bitmap = (Bitmap) bundle.get("data");
            img_show.setImageBitmap(bitmap);
        }
}        

运行效果图

这模糊的AV画质…毕竟是编码过后的Bitmap,对了,拍完的图片是不会保存到本地的,
我们可以自己写代码把图片保存到我们的SD卡里,然后再显示,这样的图片会清晰很多,
嗯,我们写代码来试下~

//定义一个保存图片的File变量
private File currentImageFile = null;

//在按钮点击事件处写上这些东西,这些是在SD卡创建图片文件的:
            @Override
            public void onClick(View v) {
                File dir = new File(Environment.getExternalStorageDirectory(),"pictures");
                if(dir.exists()){
                    dir.mkdirs();
                }
                currentImageFile = new File(dir,System.currentTimeMillis() + ".jpg");
                if(!currentImageFile.exists()){
                    try {
                        currentImageFile.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                it.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(currentImageFile));
                startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER);
            }

//onActivityResult:
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Activity.DEFAULT_KEYS_DIALER) {
        img_show.setImageURI(Uri.fromFile(currentImageFile));
        }
}

好的,非常简单,我们来看下运行结果:

相比起上面那个清晰多了~调用系统自带Carema就是这么简单~


2.自己写一个拍照页面

这里我们需要用一个SurfaceView作为我们的预览界面,使用起来同一非常简单!

运行效果图

代码实现

布局代码:activity_main.xml:一个简单的surfaceView + Button

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

    <SurfaceView
        android:id="@+id/sfv_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <Button
        android:id="@+id/btn_take"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用系统照相机" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private SurfaceView sfv_preview;
    private Button btn_take;
    private Camera camera = null;
    private SurfaceHolder.Callback cpHolderCallback = 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(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }

    private void bindViews() {
        sfv_preview = (SurfaceView) findViewById(R.id.sfv_preview);
        btn_take = (Button) findViewById(R.id.btn_take);
        sfv_preview.getHolder().addCallback(cpHolderCallback);

        btn_take.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                camera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        String path = "";
                        if ((path = saveFile(data)) != null) {
                            Intent it = new Intent(MainActivity.this, PreviewActivity.class);
                            it.putExtra("path", path);
                            startActivity(it);
                        } else {
                            Toast.makeText(MainActivity.this, "保存照片失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
    }

    //保存临时文件的方法
    private String saveFile(byte[] bytes){
        try {
            File file = File.createTempFile("img","");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes);
            fos.flush();
            fos.close();
            return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    //开始预览
    private void startPreview(){
        camera = Camera.open();
        try {
            camera.setPreviewDisplay(sfv_preview.getHolder());
            camera.setDisplayOrientation(90);   //让相机旋转90度
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

}

最后是另外一个PreviewActivity.java,这里将图片显示到界面上而已~

/**
 * Created by Jay on 2015/11/22 0022.
 */
public class PreviewActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ImageView img = new ImageView(this);
        String path = getIntent().getStringExtra("path");
        if(path != null){
            img.setImageURI(Uri.fromFile(new File(path)));
        }
        setContentView(img);
    }
}

嗯,都非常简单哈,别忘了加上权限:

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

另外,有一点要说的就是假如carema没有释放掉的话,那么下次调用carema就不会报错,
报错内容是:java.lang.RuntimeException:fail to connect to camera service
所以,需要对Carema进行release();假如一直报上面的错误,请重启手机~


3.本节示例代码下载

CaremaDemo1.zip
CaremaDemo2.zip


本节小结

好的,本节给大家讲解了如何去调用系统自带相机获取拍照后的图片,以及自己写Carema来
完成自定义相机,嘿嘿,在某些场合下我们不需要拍照预览界面,我们直接把弄一个悬浮框,
然后点击悬浮框,就触发拍照事件,这不就可以实现什么不知鬼不觉的拍摄了么?(偷拍)
嘿嘿,有点意思,要嗨自己动手写代码~

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
     由于最近忙着开发项目,好几天没来写博客了。我把最近遇到的一个小bug来和大家分享一下。      最近iOS开发中,客户端需要使用http POST去进行请求服务器。需要发送的是XML格式的,当然接收的也是XML。我们准备使用的是AFNetworking来实现。关于AFnetworking的使用以及Cocoapods包管理,请参考我的其他几篇博客:《 iOS项目开发实战——使用AFNetworking进行Http Get请求 》,《 查看进行AFNetworking请求时的头部信息 》,《 iO
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 猫咪迷宫和A*概述 正如你所看到的,现在当你在地图某处触摸的时候,猫咪将会跳到你触摸方向的相邻瓦格中去. 我们想要修改为猫咪连续移动直到你点击的位置,就像一些RPG或者点击的探险游戏一

A*寻路算法入门(五) - 2015-11-23 14:11:05

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 关于A*算法 现在你该知道如何计算每一个方块的分值了(我们将称之为F,它等于G+H),让我们看看A*算法是如何工作的. 这只猫咪将用以下重复的步骤来找到最短路径: 从开发列表中取得分值
出自 微凉一季的博客 Demo 学了一下Chris Banes大神的项目。总结一下theme相关的小知识点。先看个定义主题的不错的小case: 在values目录下建立两个命名为themes的文件: themes.xml resources xmlns:android= "http://schemas.android.com/apk/res/android" style name= "Platform.Theme.AnDream" parent= "Theme.AppCompat.Light.NoActi

Picasso学习笔记 - 2015-11-22 17:11:38

下面是我在学习 Picasso 过程中做的笔记,思路可能有些凌乱,如果阅读过程中有发现不准确或者错误的地方欢迎交流(微博@楚奕RJ) 内容主要分三部分,第一部分是picasso的基本使用,第二部分是picasso的源码阅读,最后一部分是关于源码中一些细节的梳理. 关于图片加载库的思考 我们为什么要用图片库呢? 图片库通常会对图片加载逻辑进行封装、优化,比如多级缓存/异步线程调度/图片压缩变换,有了这些特性,开发者不再需要关注内存占用、 OOM、网络请求等问题,而只需关注业务本身的逻辑,这对提高生产效率有很
在Activity的启动流程中,共有4个阶段,下面将一一道来。 1.第一阶段——启动信息翻译以及服务调用 这一阶段的工作主要是在应用程序本地完成的,主要为启动Activity做一些参数上的准备,然后服务的代理将这些参数转发到服务,开始Activity启动的流程,如下图: 2.第二阶段——Activity的相关处理 到了这个阶段,工作就已经由ActivityManagerService处理了。在此阶段,它将完成对ActivityStack及应用程序进程的相关处理,如下图: 在以上流程中,我们完成了对Acti
38. Android 反射资源工具ReflectionUtil Android 反射资源工具ReflectionUtil 工具代码 工具使用 工具代码 ReflectionUtil public class ReflectionUtil { public enum ResourcesType { styleable, style, string, mipmap, menu, layout, integer, id, drawable, dimen, color, bool, attr, anim } /

猫猫学iOS之安装cocoapods - 2015-11-22 17:11:17

啥事cocoa pods 不解释,自己看这里只有一次安装流程,猫猫的安装流程。 打开命令行,我用的是ruby安装,mac自带ruby,啥是ruby,不解释,因为开始我也不懂,就当他是命令行。 1:安装命令: sudo gem install cocoapods 然后提示输入密码,不过因为他的软件源(理解为下载地址)是国外的,咱们不能支持到,如图 2:换成淘宝源头,当然有些网上放出的地址不对比如我这样操作: 如图,报错404了 下面是可以的,能行的。 # 删除默认的官方源 gem sources -r ht

IOS_swift文件系统 - 2015-11-22 17:11:16

func files(){ //应用根目录 let dir = NSHomeDirectory(); NSLog("dir = \(dir)") // 文档目录 let doc = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] NSLog("doc = \(doc)") // library目录 let library = NSSearchPathForDirectoriesInDomai

A*寻路算法入门(一) - 2015-11-22 17:11:09

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 该篇博客由iOS课程团队的 Johann Fradj 发布,他现在是一个全职开发iOS的开发者.他是 Hot Apps Factory (其是 App Cooker 的创造者)的共同创