浅谈 安卓-调用相机拍照

我学习安卓看的是《第一行代码 Android》这本书,今天我来简单谈一下“8.3.2 调用摄像头拍照”这一小节中的代码。

这一节的代码逻辑作者没有讲的特别清晰,接下来我为大家来分析一下代码。

代码如下:

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

takePhoto=(Button)findViewById(R.id.take_photo);

picture=(ImageView)findViewById(R.id.picture);

//chooseFromAlbum=(Button)findViewById(R.id.choose_from_album);

takePhoto.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View arg0) {

File outputImage=new File(Environment.getExternalStorageDirectory(),"tempImage.jpg");

try {

if(outputImage.exists())

{

outputImage.delete();

}

outputImage.createNewFile();

}

catch(IOException e){

e.printStackTrace();

}

imageUri=Uri.fromFile(outputImage);

Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, TAKE_PHOTO);

}

});

}

@Override

protected void onActivityResult(int requestCode,int resultCode,Intent data)

{

switch(requestCode)

{

case TAKE_PHOTO:

if(resultCode==RESULT_OK)

{

Intent intent=new Intent("com.android.camera.action.CROP");

intent.setDataAndType(imageUri, "image/*");

intent.putExtra("scale", false);

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, CROP_PHOTO);

}

break;

case CROP_PHOTO:

if(resultCode==RESULT_OK)

{

try {

Bitmap bitmap=BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));

picture.setImageBitmap(bitmap);

}

catch(FileNotFoundException e){

e.printStackTrace();

}

}

break;

default:

break;

}


从代码可以分成几块来看。

一是启动相机程序。

imageUri=Uri.fromFile(outputImage);

Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, TAKE_PHOTO);

这一节中用到了一个比较特别的方法,startActivityForResult。这个我们稍后再讲。先看一下上面的这几行代码。书中有提到的我在这里就不再赘述了,重点讲一些书上没提到的。outImage是我们定义的一个文件类的变量,首先需要把它转化为一个uri对象,这个uri对象就是我们定义的outImage文件所在的路径。然后我们定义了一个隐式intent,作为开启活动的intent来启用相机程序。然后调用putExtra函数,MediaStore.EXTRA_OUTPUT
属性可以理解为,不论这个intent是用来调用照片或是音乐等等,执行完startActivityResult后生成的东西会保存在imageUri这个路径当中。

二是裁剪图片。

书上有提到,startActivityForResult这个函数执行后,会返回到onActivityResult这个函数,所以可以在onActivityResult里写在执行完相机程序后裁剪图片的代码。case TAKE_PHOTO和case CROP_PHOTO是requestcode变量,是在执行startActivityForResult(intent,requestcode)之后传入onActivityResult函数的,用来判断此时是刚拍完相片要裁剪(case TAKE_PHOTO)还是刚裁剪完要显示在ImageView上(case CROP_PHOTO)。至于resultcode在程序中我们只看到一种值,就是RESULT_OK,那是因为我们的这个项目中就只有一个活动,当活动不止一个时,resultcode可以用于判断是哪个活动返回的数据,通过activity.RESULT_OK。讲解了这两个函数,接下来继续看代码。

Intent intent=new Intent("com.android.camera.action.CROP");

intent.setDataAndType(imageUri, "image/*");

intent.putExtra("scale", false);

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, CROP_PHOTO);

这里的intent和刚才调用手机拍照类似,它们的action是android内置的,只要你传入这个intent,手机里的对应活动就会响应。setDataAndType函数是用来打开文件的,现在我们已经调用相机拍好了照片,接下来就要打开这个相片文件,对它进行裁剪。setDataAndType函数利用了Uri路径打开相片,第二个参数是文件的类型。然后通过putExtra(MediaStore.EXTRA_OUTPUT, imageUri)再次设置裁剪完图片后的存储位置,最后调用活动。

接下来就是裁剪图片后在页面上的显示。我还没太弄明白为什么要用Bitmap来显示,不过这个知识点不难,我就不说了。

最后补充一个小细节,相信大家也发现了我漏了一块没讲,代码如下。

if(outputImage.exists())

{

outputImage.delete();

}

outputImage.createNewFile();

这段代码理解起来也很简单。在我们调用相机拍照并且已经显示在页面上之后,如果我们还需要重新拍照来在页面上显示新的图片,应该判断此时页面上是否有图片,如果有的话将它删除并且重新创造一个文件。这是细节方面的问题,大家在写demo的时候也要尽量考虑的全面,将功能做到尽可能完善。

你可能感兴趣的:(浅谈 安卓-调用相机拍照)