[关闭]
@coder-pig 2015-11-22T15:55:31.000000Z 字数 4699 阅读 5393

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

Android基础入门教程


本节引言

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


1.调用系统自带Carema

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

  1. Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  2. startActivityForResult(it,Activity.DEFAULT_KEYS_DIALER);
  3. //重写onActivityResult方法
  4. @Override
  5. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  6. if(requestCode == Activity.RESULT_OK){
  7. Bundle bundle = data.getExtras();
  8. Bitmap bitmap = (Bitmap) bundle.get("data");
  9. img_show.setImageBitmap(bitmap);
  10. }
  11. }

运行效果图

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

  1. //定义一个保存图片的File变量
  2. private File currentImageFile = null;
  3. //在按钮点击事件处写上这些东西,这些是在SD卡创建图片文件的:
  4. @Override
  5. public void onClick(View v) {
  6. File dir = new File(Environment.getExternalStorageDirectory(),"pictures");
  7. if(dir.exists()){
  8. dir.mkdirs();
  9. }
  10. currentImageFile = new File(dir,System.currentTimeMillis() + ".jpg");
  11. if(!currentImageFile.exists()){
  12. try {
  13. currentImageFile.createNewFile();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  19. it.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(currentImageFile));
  20. startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER);
  21. }
  22. //onActivityResult:
  23. @Override
  24. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  25. if (requestCode == Activity.DEFAULT_KEYS_DIALER) {
  26. img_show.setImageURI(Uri.fromFile(currentImageFile));
  27. }
  28. }

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

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


2.自己写一个拍照页面

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

运行效果图

代码实现

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

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical">
  5. <SurfaceView
  6. android:id="@+id/sfv_preview"
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content"
  9. android:layout_weight="1" />
  10. <Button
  11. android:id="@+id/btn_take"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:text="调用系统照相机" />
  15. </LinearLayout>

MainActivity.java

  1. public class MainActivity extends AppCompatActivity {
  2. private SurfaceView sfv_preview;
  3. private Button btn_take;
  4. private Camera camera = null;
  5. private SurfaceHolder.Callback cpHolderCallback = new SurfaceHolder.Callback() {
  6. @Override
  7. public void surfaceCreated(SurfaceHolder holder) {
  8. startPreview();
  9. }
  10. @Override
  11. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  12. }
  13. @Override
  14. public void surfaceDestroyed(SurfaceHolder holder) {
  15. stopPreview();
  16. }
  17. };
  18. @Override
  19. protected void onCreate(Bundle savedInstanceState) {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_main);
  22. bindViews();
  23. }
  24. private void bindViews() {
  25. sfv_preview = (SurfaceView) findViewById(R.id.sfv_preview);
  26. btn_take = (Button) findViewById(R.id.btn_take);
  27. sfv_preview.getHolder().addCallback(cpHolderCallback);
  28. btn_take.setOnClickListener(new View.OnClickListener() {
  29. @Override
  30. public void onClick(View v) {
  31. camera.takePicture(null, null, new Camera.PictureCallback() {
  32. @Override
  33. public void onPictureTaken(byte[] data, Camera camera) {
  34. String path = "";
  35. if ((path = saveFile(data)) != null) {
  36. Intent it = new Intent(MainActivity.this, PreviewActivity.class);
  37. it.putExtra("path", path);
  38. startActivity(it);
  39. } else {
  40. Toast.makeText(MainActivity.this, "保存照片失败", Toast.LENGTH_SHORT).show();
  41. }
  42. }
  43. });
  44. }
  45. });
  46. }
  47. //保存临时文件的方法
  48. private String saveFile(byte[] bytes){
  49. try {
  50. File file = File.createTempFile("img","");
  51. FileOutputStream fos = new FileOutputStream(file);
  52. fos.write(bytes);
  53. fos.flush();
  54. fos.close();
  55. return file.getAbsolutePath();
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. }
  59. return "";
  60. }
  61. //开始预览
  62. private void startPreview(){
  63. camera = Camera.open();
  64. try {
  65. camera.setPreviewDisplay(sfv_preview.getHolder());
  66. camera.setDisplayOrientation(90); //让相机旋转90度
  67. camera.startPreview();
  68. } catch (IOException e) {
  69. e.printStackTrace();
  70. }
  71. }
  72. //停止预览
  73. private void stopPreview() {
  74. camera.stopPreview();
  75. camera.release();
  76. camera = null;
  77. }
  78. }

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

  1. /**
  2. * Created by Jay on 2015/11/22 0022.
  3. */
  4. public class PreviewActivity extends AppCompatActivity {
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. ImageView img = new ImageView(this);
  9. String path = getIntent().getStringExtra("path");
  10. if(path != null){
  11. img.setImageURI(Uri.fromFile(new File(path)));
  12. }
  13. setContentView(img);
  14. }
  15. }

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

  1. <uses-permission android:name="android.permission.CAMERA"/>
  2. <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来
完成自定义相机,嘿嘿,在某些场合下我们不需要拍照预览界面,我们直接把弄一个悬浮框,
然后点击悬浮框,就触发拍照事件,这不就可以实现什么不知鬼不觉的拍摄了么?(偷拍)
嘿嘿,有点意思,要嗨自己动手写代码~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注