Android开发中,怎样调用摄像机拍照以及怎样从本地图库中选取照片

这是属于我的第一篇博文,首先说明一下,文章属性为原创,其实不能说是原创,我是在学习的过程中根据自己的理解整理的。文章内容大多为书本上的内容,书本是郭霖的《第一行代码》。

       正文:现在很多应用程序会调用摄像头的拍照功能,比如哪个程序要上传一张图片作为用户头像,这是启用摄像头拍照会很方便。当然,还有第二种方法,就是在本地图库选取已经被保存的图片。现在,我就根据自己学习的过程,将这部分只是进行整理,如下:



public class MainActivity extends AppCompatActivity {
    private Button button;
    private ImageView imageView;
    private Uri imageuri;
    private Button choose;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        button = (Button) findViewById(R.id.button);
        imageView = (ImageView) findViewById(R.id.imageView);
        choose = (Button) findViewById(R.id.button2);
        
        //此按钮事件是拍照,启动摄像机的功能
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //创建一个File对象,用于存储接下来照相机拍摄的照片
                File file = new File(Environment.getExternalStorageDirectory(), "output_image.jpg");
                if (file.exists()) {
                    file.delete();
                }
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                imageuri = Uri.fromFile(file);
                //下面这个intent对象就是用于启动照相机的
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);//指定图片的输出地址
                startActivityForResult(intent, 1);//启动照相机,这里传入的参数1,其实只要是固定一个值都行,
                                                  //比较好的做法是声明一个全局常量比较好,我在这里没有这么做。
            }
        });
        //此按钮事件是选取本地图片,启动相册
        choose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("android.intent.action.GET_CONTENT");//这个intent对象是用于开启本地图库的
                intent.setType("image/*");//给intent对象设置必要的参数
                startActivityForResult(intent, 3);//开启本地图库
            }
        });
       
    }

    @Override
    //因为我们用startActivityForResult方法启动活动,所有它们处理完结果后,会回调上一个活动的onActivityResult方法,这里我们就在MainActivity重写此方法
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case 1://就是照相机拍好了照片来回调的这个方法的case 1,这个时候我们想要启动照片的裁剪程序
                if (resultCode == RESULT_OK) {
                    Intent intent = new Intent("com.android.camera.action.CROP");//这个intent对象启动裁剪程序
                    intent.putExtra("scale", true);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);//设置图片的输出地址
                    intent.setDataAndType(imageuri, "image/*");//设置图片的返回格式
                    startActivityForResult(intent, 2);
                }
                break;
            case 2://裁剪好了的图片回调此方法的case 2,这个时候我们就要将裁剪好的图片设置到imageview里
                if (resultCode == RESULT_OK) {
                    try {
               
                        //BitmapFactory的decodeStream()方法将照片解析成Bitmap对象
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageuri));
                        imageView.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case 3://本地图库选取图片后,回调此方法的case 3,在这里我们主要做的就是图片的处理工作
                if (resultCode == RESULT_OK) {
                    //判断系统版本号,如果API>19,即Android 4.4版本以上用这个方法处理图片
                    if (Build.VERSION.SDK_INT >= 19) {
                        handleImageOnKitKat(data);
                    }
                    else {
                        //android4.4以下,用这个方法处理图片
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
            default:
                break;
        }

    }


    @TargetApi(19)
    private void handleImageOnKitKat(Intent data) {
        //其实这个方法的目标很简单,就是要获取图片的真实路径imagepath,然后我们会再提供一个方法将imagepath作为参数来显示图片
        String imagepath = null;
        //android4.4以上的版本,我们获取的图片uri不是真实的图片uri,是封装过的,不能直接用来显示图片,我们要进行解析
        Uri uri = data.getData();//通过传入intent参数来获取信息,图片的内容uri

        //接下来的内容看似复杂,其实很简单,我们进行了很多判断,首先判断这个uri是否为document类型,
        //如果是document类型的话,就取出document id处理,如果不是,就普通方式处理
        //另外,我们又对uri的权限部分进行判断,如果是media格式,则document id还要再次进行解析
        if (DocumentsContract.isDocumentUri(this, uri))//判断如果是document类型,则通过document id处理
        {
            String docId = DocumentsContract.getDocumentId(uri);//通过uri获取document id。
            //判断我们的uri的权限部分,media格式,对document id用":"分割,取出真正的数字id
            if ("com.android.provider.media.documents".equals(uri.getAuthority())) {
                //split方法返回的结果是一个数组,我们选取第二个,即角标为1,这样我们就解析出数字格式的id
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;//用id构建新的条件语句,并且在后面query()方法
                                                                          //进行数据库查询是作为参数,主要是约束我们的查询条件
                //getImagepath()方法是我们自己提供的用来获取图片真实路径
                imagepath = getImagepath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
                
            } else if ("com.android.provider.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("conten://downloads/public_downloads"), Long.valueOf(docId));
                imagepath = getImagepath(contentUri, null);
                
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            //如果不是document类型的uri,则使用普通方法处理
            imagepath = getImagepath(uri, null);
            
        }
        displayImage(imagepath);//最后,我们根据路径显示图片
    }

    private void handleImageBeforeKitKat(Intent data)
    {
        Uri uri=data.getData();
        String imagepath=getImagepath(uri,null);
        displayImage(imagepath);
        
    }

    //获取图片路径的方法
    private String getImagepath(Uri uri, String selection) {
        String path = null;
        //通过uri和selection获取真实的图片路径
        //其实selection就是一个约束条件,让我们指定查询哪一行,就好比name=lee,age=18这样
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToNext()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }
        
        return path;
    }
    //显示图片的方法
    private void displayImage(String imagepath)
    {
        if (imagepath!=null)
        {
            //BitmapFactory的decodeFile解析路径,使图片为Bitmap对象
            Bitmap bitmap=BitmapFactory.decodeFile(imagepath);
            imageView.setImageBitmap(bitmap);
        }else {
            Toast.makeText(this,"图片获取失败",Toast.LENGTH_SHORT).show();
        }
    }



        其实,很多照片即使裁剪了以后体积还是很大,直接加载到内存,很容易使程序崩溃。更好的做法是根据项目需求对照片进行适当的压缩,然后加载到内存。这个时候就要考验我们的阅读文档能力啦,学无止境啊。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值