经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android实现简单的照相功能
来源:jb51  时间:2022/3/29 11:46:58  对本文有异议

一个简单的照相功能,拍照之后在另一个activit中显示出拍照的图片。
首先是布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. ? ? xmlns:app="http://schemas.android.com/apk/res-auto"
  4. ? ? xmlns:tools="http://schemas.android.com/tools"
  5. ? ? android:layout_width="match_parent"
  6. ? ? android:layout_height="match_parent"
  7. ? ? android:orientation="vertical"
  8. ? ? tools:context=".MainActivity">
  9.  
  10. ? ? <SurfaceView
  11. ? ? ? ? android:id="@+id/sf"
  12. ? ? ? ? android:layout_width="match_parent"
  13. ? ? ? ? android:layout_height="0dp"
  14. ? ? ? ? android:layout_weight="1"
  15. ? ? ? ? android:text="Hello World!"
  16. ? ? ? ? app:layout_constraintBottom_toBottomOf="parent"
  17. ? ? ? ? app:layout_constraintLeft_toLeftOf="parent"
  18. ? ? ? ? app:layout_constraintRight_toRightOf="parent"
  19. ? ? ? ? app:layout_constraintTop_toTopOf="parent" />
  20. ? ? <Button
  21. ? ? ? ? android:id="@+id/bt"
  22. ? ? ? ? android:layout_width="match_parent"
  23. ? ? ? ? android:layout_height="wrap_content"
  24. ? ? ? ? android:text="拍照"></Button>
  25.  
  26. </LinearLayout>

一个SurfaceView呈现相机拍摄的画面;
button是点击后拍照功能;

  • 初始化一个SurfaceView 控件;
  1. sf = findViewById(R.id.sf);
  2. ? ? ? ? sf.getHolder().addCallback(new SurfaceHolder.Callback() {
  3. ? ? ? ? ? ? @Override
  4. ? ? ? ? ? ? public void surfaceCreated(SurfaceHolder holder) {
  5. ? ? ? ? ? ? ? ? start();
  6. ? ? ? ? ? ? }
  7.  
  8. ? ? ? ? ? ? @Override
  9. ? ? ? ? ? ? public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  10.  
  11. ? ? ? ? ? ? }
  12.  
  13. ? ? ? ? ? ? @Override
  14. ? ? ? ? ? ? public void surfaceDestroyed(SurfaceHolder holder) {
  15. ? ? ? ? ? ? ? ? stop();
  16. ? ? ? ? ? ? }
  17. ? ? ? ? }

简单说明一下Surface与SurfaceHolder.Callback之间的联系。

Surface是android的一个重要元素,用于android画面的图形绘制。而SurfaceView 是视图(View)的一个继承类,每一个SurfaceView都内嵌封装一个Surface。通过调用SurfaceHolder可以调用 SurfaceView,控制图形的尺寸和大小。而SurfaceHolder 是通过getholder()来取得。创立SurfaceHolder 对象后,用SurfaceHolder.Callback()来回调SurfaceHolder,对SurfaceView进行控制。

surfaceCreated 当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。

surfaceChanged 当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。

surfaceDestroyed 当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。

创建camera对象,(注意要用import android.hardware.Camera;这个包下的)

  1. public void start() {
  2. ?camera = Camera.open();
  3. ? ? ? ? try {
  4. ? ? ? ? ? ? camera.setPreviewDisplay(sf.getHolder());
  5. ? ? ? ? ? ? camera.startPreview();//开始预览画面
  6. ? ? ? ? ? ? camera.setDisplayOrientation(90);//拍摄画面旋转90度
  7. ? ? ? ? } catch (IOException e) {
  8. ? ? ? ? ? ? e.printStackTrace();
  9. ? ? ? ? }
  10. ? ? }

把刚才创建的SurfaceHolder对象设置到camera中;
以上步骤在surfaceCreated()方法中调用;

在界面结束的时候释放相机资源:

  1. public void stop() {
  2. ? ? ? ? camera.stopPreview();
  3. ? ? ? ? camera.release();
  4. ? ? }

点击拍照按钮之后执行的步骤

  1. findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
  2. ? ? ? ? ? ? @Override
  3. ? ? ? ? ? ? public void onClick(View v) {
  4. ? ? ? ? ? ? ? ? camera.takePicture(null, null, new Camera.PictureCallback() {//开始拍照;
  5. ? ? ? ? ? ? ? ? ? ? @Override
  6. ? ? ? ? ? ? ? ? ? ? public void onPictureTaken(byte[] data, Camera camera) {//拍完之后回调;
  7. ? ? ? ? ? ? ? ? ? ? ? ? String path = null;
  8.  
  9. ? ? ? ? ? ? ? ? ? ? ? ? if ((path = savephoto(data)) != null) {
  10. ? ? ? ? ? ? ? ? ? ? ? ? ? ? Intent in = new Intent(MainActivity.this, MyActivity.class);
  11. ? ? ? ? ? ? ? ? ? ? ? ? ? ? in.putExtra("path", path);
  12. ? ? ? ? ? ? ? ? ? ? ? ? ? ? startActivity(in);
  13. ? ? ? ? ? ? ? ? ? ? ? ? } else {
  14. ? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "save photo fail", Toast.LENGTH_LONG).show();
  15. ? ? ? ? ? ? ? ? ? ? ? ? }
  16.  
  17. ? ? ? ? ? ? ? ? ? ? }
  18. ? ? ? ? ? ? ? ? });
  19. ? ? ? ? ? ? }
  20. ? ? ? ? });

savephoto()保存当前相片资源到临时文件中;

  1. private String savephoto(byte[] bytes) {
  2. ? ? ? ? try {
  3. ? ? ? ? ? ? File f = File.createTempFile("img", "");//前缀,后缀
  4. ? ? ? ? ? ? FileOutputStream fos = new FileOutputStream(f);
  5. ? ? ? ? ? ? fos.write(bytes);
  6. ? ? ? ? ? ? fos.flush();
  7. ? ? ? ? ? ? fos.close();
  8. ? ? ? ? ? ? return f.getAbsolutePath();
  9. ? ? ? ? } catch (IOException e) {
  10. ? ? ? ? ? ? e.printStackTrace();
  11. ? ? ? ? }
  12. ? ? ? ? return null;
  13. ? ? }

将二进制数据存储到临时文件中,并且返回文件路径;

拍照之后跳转到另个界面显示:

  1. package com.example.camera;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.net.Uri;
  6. import android.os.Bundle;
  7. import android.widget.ImageView;
  8.  
  9. import androidx.annotation.Nullable;
  10.  
  11. import java.io.File;
  12.  
  13. public class MyActivity extends Activity {
  14. ? ? private ImageView iv;
  15.  
  16. ? ? @Override
  17. ? ? protected void onCreate(@Nullable Bundle savedInstanceState) {
  18. ? ? ? ? super.onCreate(savedInstanceState);
  19. ? ? ? ? iv=new ImageView(MyActivity.this);
  20.  
  21. ? ? ? ? setContentView(iv);
  22. ? ? ? ? Intent intent =getIntent();
  23. ? ? ? ? String path=intent.getStringExtra("path");
  24. ? ? ? ? if (path!=null){
  25. ? ? ? ? ? ? iv.setImageURI(Uri.fromFile(new File(path)));
  26. ? ? ? ? }
  27. ? ? }
  28. }

iv.setImageURI(Uri.fromFile(new File(path)));通过文件路径,创建一个文件;

主activity的代码如下:

  1. package com.example.camera;
  2.  
  3. import android.content.Intent;
  4. import android.hardware.Camera;
  5. import android.os.Bundle;
  6. import android.view.SurfaceHolder;
  7. import android.view.SurfaceView;
  8. import android.view.View;
  9. import android.widget.Toast;
  10.  
  11. import androidx.appcompat.app.AppCompatActivity;
  12.  
  13. import java.io.File;
  14. import java.io.FileOutputStream;
  15. import java.io.IOException;
  16.  
  17.  
  18. public class MainActivity extends AppCompatActivity {
  19. ? ? private SurfaceView sf;
  20. ? ? private Camera camera;
  21.  
  22. ? ? @Override
  23. ? ? protected void onCreate(Bundle savedInstanceState) {
  24. ? ? ? ? super.onCreate(savedInstanceState);
  25. ? ? ? ? setContentView(R.layout.activity_main);
  26. ? ? ? ? findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() {
  27. ? ? ? ? ? ? @Override
  28. ? ? ? ? ? ? public void onClick(View v) {
  29. ? ? ? ? ? ? ? ? camera.takePicture(null, null, new Camera.PictureCallback() {//开始拍照;
  30. ? ? ? ? ? ? ? ? ? ? @Override
  31. ? ? ? ? ? ? ? ? ? ? public void onPictureTaken(byte[] data, Camera camera) {//拍完之后回调;
  32. ? ? ? ? ? ? ? ? ? ? ? ? String path = null;
  33.  
  34. ? ? ? ? ? ? ? ? ? ? ? ? if ((path = savephoto(data)) != null) {
  35. ? ? ? ? ? ? ? ? ? ? ? ? ? ? Intent in = new Intent(MainActivity.this, MyActivity.class);
  36. ? ? ? ? ? ? ? ? ? ? ? ? ? ? in.putExtra("path", path);
  37. ? ? ? ? ? ? ? ? ? ? ? ? ? ? startActivity(in);
  38. ? ? ? ? ? ? ? ? ? ? ? ? } else {
  39. ? ? ? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this, "save photo fail", Toast.LENGTH_LONG).show();
  40. ? ? ? ? ? ? ? ? ? ? ? ? }
  41.  
  42. ? ? ? ? ? ? ? ? ? ? }
  43. ? ? ? ? ? ? ? ? });
  44. ? ? ? ? ? ? }
  45. ? ? ? ? });
  46.  
  47.  
  48. ? ? ? ? sf = findViewById(R.id.sf);
  49. ? ? ? ? sf.getHolder().addCallback(new SurfaceHolder.Callback() {
  50. ? ? ? ? ? ? @Override
  51. ? ? ? ? ? ? public void surfaceCreated(SurfaceHolder holder) {
  52. ? ? ? ? ? ? ? ? start();
  53. ? ? ? ? ? ? }
  54.  
  55. ? ? ? ? ? ? @Override
  56. ? ? ? ? ? ? public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  57.  
  58. ? ? ? ? ? ? }
  59.  
  60. ? ? ? ? ? ? @Override
  61. ? ? ? ? ? ? public void surfaceDestroyed(SurfaceHolder holder) {
  62. ? ? ? ? ? ? ? ? stop();
  63. ? ? ? ? ? ? }
  64. ? ? ? ? });
  65.  
  66. ? ? }
  67.  
  68. ? ? private String savephoto(byte[] bytes) {
  69. ? ? ? ? try {
  70. ? ? ? ? ? ? File f = File.createTempFile("img", "");//前缀,后缀
  71. ? ? ? ? ? ? FileOutputStream fos = new FileOutputStream(f);
  72. ? ? ? ? ? ? fos.write(bytes);
  73. ? ? ? ? ? ? fos.flush();
  74. ? ? ? ? ? ? fos.close();
  75. ? ? ? ? ? ? return f.getAbsolutePath();
  76. ? ? ? ? } catch (IOException e) {
  77. ? ? ? ? ? ? e.printStackTrace();
  78. ? ? ? ? }
  79. ? ? ? ? return null;
  80. ? ? }
  81.  
  82. ? ? public void start() {
  83. ? ? ? ? camera = Camera.open();
  84. ? ? ? ? try {
  85. ? ? ? ? ? ? camera.setPreviewDisplay(sf.getHolder());
  86. ? ? ? ? ? ? camera.startPreview();//开始预览画面
  87. ? ? ? ? ? ? camera.setDisplayOrientation(90);//拍摄画面旋转90度
  88. ? ? ? ? } catch (IOException e) {
  89. ? ? ? ? ? ? e.printStackTrace();
  90. ? ? ? ? }
  91. ? ? }
  92.  
  93. ? ? public void stop() {
  94. ? ? ? ? camera.stopPreview();
  95. ? ? ? ? camera.release();
  96. ? ? }
  97.  
  98. }

记得需要添加照相机权限:

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号