基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片

向右看齐 2023-10-17 15:48 153阅读 0赞

基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片

写一个简单的例子,实现一个常见的开发功能:拍照功能。
技术路线:通过TextureView的通道获取SurfaceTexture作为相机的预览,然后通过Camera的take方法把相机抓取的byte字节数据转换为Bitmap,然后存放到手机的存储器上,至此,一个最简单的拍照功能完成。
注意,本例如果运行在Android高版本(6.0+,7.0+或更高),需要多写运行时权限申请代码。本例出于功能演示,不再冗余的写这部分代码。只给出最骨干的关键代码逻辑。

布局文件activity_main.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:background="@android:color/holo_blue_light"
  7. tools:context="zhangphil.view.MainActivity">
  8. <zhangphil.view.MyTextureView
  9. android:id="@+id/textureView"
  10. android:layout_width="300dp"
  11. android:layout_height="200dp"
  12. android:layout_centerInParent="true" />
  13. <Button
  14. android:id="@+id/capture"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_alignParentBottom="true"
  18. android:layout_centerHorizontal="true"
  19. android:text="拍摄" />
  20. </RelativeLayout>

MyTextureView.java:

  1. package zhangphil.view;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.SurfaceTexture;
  6. import android.hardware.Camera;
  7. import android.os.Environment;
  8. import android.util.AttributeSet;
  9. import android.util.Log;
  10. import android.view.TextureView;
  11. import java.io.BufferedOutputStream;
  12. import java.io.File;
  13. import java.io.FileOutputStream;
  14. /**
  15. * Created by Phil on 2017/9/13.
  16. */
  17. public class MyTextureView extends TextureView {
  18. public Camera mCamera;
  19. public MyTextureView(Context context, AttributeSet attrs) {
  20. super(context, attrs);
  21. init();
  22. }
  23. private void init() {
  24. mCamera = Camera.open();
  25. this.setSurfaceTextureListener(new SurfaceTextureListener() {
  26. @Override
  27. public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
  28. try {
  29. mCamera.setPreviewTexture(surfaceTexture);
  30. mCamera.startPreview();
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. @Override
  36. public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
  37. }
  38. @Override
  39. public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
  40. mCamera.stopPreview();
  41. mCamera.release();
  42. mCamera = null;
  43. return true;
  44. }
  45. @Override
  46. public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
  47. }
  48. });
  49. }
  50. public void take() {
  51. if(mCamera!=null)
  52. mCamera.takePicture(null, null, mPictureCallback);
  53. }
  54. Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
  55. @Override
  56. public void onPictureTaken(byte[] data, Camera camera) {
  57. mCamera.stopPreview();
  58. new FileSaver(data).save();
  59. }
  60. };
  61. private class FileSaver implements Runnable {
  62. private byte[] buffer;
  63. public FileSaver(byte[] buffer) {
  64. this.buffer = buffer;
  65. }
  66. public void save() {
  67. new Thread(this).start();
  68. }
  69. @Override
  70. public void run() {
  71. try {
  72. File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "zhangphil.png");
  73. file.createNewFile();
  74. FileOutputStream os = new FileOutputStream(file);
  75. BufferedOutputStream bos = new BufferedOutputStream(os);
  76. Bitmap bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
  77. bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
  78. bos.flush();
  79. bos.close();
  80. os.close();
  81. Log.d("照片已保存", file.getAbsolutePath());
  82. mCamera.startPreview();
  83. } catch (Exception e) {
  84. e.printStackTrace();
  85. }
  86. }
  87. }
  88. }

MainActivity.java:

  1. package zhangphil.view;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. public class MainActivity extends AppCompatActivity {
  6. private MyTextureView textureView;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. textureView = (MyTextureView) findViewById(R.id.textureView);
  12. findViewById(R.id.capture).setOnClickListener(new View.OnClickListener() {
  13. @Override
  14. public void onClick(View view) {
  15. textureView.take();
  16. }
  17. });
  18. }
  19. }

权限:

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

代码运行结果:

Center

发表评论

表情:
评论列表 (有 0 条评论,153人围观)

还没有评论,来说两句吧...

相关阅读