Android 简单相机和照片查看器的制作
来源:互联网 发布:mac os 10.11原版镜像 编辑:程序博客网 时间:2024/05/13 05:51
第一篇:本人的第一篇博客
相机是手机内部必不可少的一个软件…那我们如何做出一个简单的相机呢?在Android内部提供了一个内部类android.view.SurfaceHolder这个类,这个类提供了SurfaceView,这个类可以帮助我们实现照相功能…
1.实现拍照
- 实现拍照就必须要有对相机的访问权限
- 拍照所得的照片的存储就需要有对SD卡的访问权限以及对SD卡中文件夹的创建和删除的权限
-
添加到AndroidManifest.xml中
<uses-permission android:name="android.permission.WRITE_EXTENAL_STORAGE"/> //sdcard的写权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> //sdcard的读权限 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> //允许挂载和反挂载文件系统可移动存储
调用摄像机
//现在的相机一般都有两个摄像头,我们需要定义我们想要打开哪个摄像头,默认的是后置的摄像头...这里打开的也是后置的摄像头...
if(Camera.getNumberOfCameras()==2){
camera=Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}else{
camera=Camera.open(0);
}
获取相机参数
Parameters param=Camera1.this.camera.getParameters()
//Camera1是我所建的类名,根据实际情况更改
预览
try { Camera1.this.camera.setPreviewDisplay(Camera1.this.surfaceHolder);//设置我们预览时的SurfaceHolder...
} catch (IOException e) {
e.printStackTrace();
}
Camera1.this.camera.startPreview();//开始预览...
拍照
Camera1.this.camera.takePicture(shutter, raw, jpeg);//Camera.takePicture(shutterCallback,rawCallback,pictureCallback ); 三个回调参数分别代表:按下快门执行的代码;如需要处理raw执行的代码;图片存储执行的代码。
存储
针对Android 6.0以上,除了需要静态权限,还需要动态权限。
ActivityCompat.requestPermissions(Camera1.this, new String[]{android
.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
弹出请求后获得权限立马进入public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)中。
@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults) { switch (requestCode) { case 1: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //创建文件夹 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //这里执行获取权限的代码。 } break; } } }
新建文件夹
String filename = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator + "CameraPhoto" ;File file = new File(filename);if (!file.exists()) {//如果不存在,就创建一个。最后一般来说会在根目录下找到CameraPhoto文件夹 file.mkdirs();}
将照片转化成字节数据
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
将照片存入file里面
FileOutputStream buf = new FileOutputStream(filename+File.separator+"picture.jpg"); bmp.compress(Bitmap.CompressFormat.JPEG, 100, buf);
最后我们可以在CameraPhoto文件中找到名为picture.jpg的照片。因为这里是固定的照片名,每次拍照存储都把之前的照片替换掉了,所以只能存储一张照片。当然可以在文件名上面加上System.currentTimeMillis()函数,这样每次照片的名字都不一样。
完整代码
- Activity代码
package com.example.myapplication;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.PixelFormat;import android.hardware.Camera;import android.os.Bundle;import android.os.Environment;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.view.Display;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.WindowManager;import android.widget.Button;import android.widget.Toast;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;/** * Created by 邓磊 on 2017/7/30. */public class Camera1 extends Activity implements View.OnClickListener { private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private Camera camera = null; private boolean previewrunning = true; private Button TakePhoto; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏显示... super.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//高亮显示... setContentView(R.layout.camera_main); TakePhoto = (Button) findViewById(R.id.TakePhoto); TakePhoto.setOnClickListener(this); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); surfaceHolder = surfaceView.getHolder(); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceHolder.setFixedSize(480, 800); surfaceHolder.addCallback(new SurfaceHolder.Callback() { //这里就很清晰了,在使用到了SurfaceView时必然要获取SurfaceHolder接口,然后进行回调.. @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub if (Camera1.this.camera != null) { if (Camera1.this.previewrunning) { Camera1.this.camera.stopPreview(); Camera1.this.previewrunning = false; } Camera1.this.camera.release(); } } @SuppressLint("NewApi") @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub if (Camera.getNumberOfCameras() == 2) {//获取相机... camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); } else { camera = Camera.open(0); } camera.setDisplayOrientation(90);//这个就是设置屏幕需要旋转90度,一般没这句话屏幕内的东西都是纵向的... WindowManager manager = (WindowManager) Camera1.this.getSystemService(Context.WINDOW_SERVICE);//获取窗口服务.. Display display = manager.getDefaultDisplay();//获取display对象.. Camera.Parameters param = Camera1.this.camera.getParameters();//获取参数 param.setPreviewSize(display.getWidth(), display.getHeight());//设置预览时图片的大小.. param.setPictureSize(display.getWidth(), display.getHeight());//设置拍照后图片的大小.. param.setPreviewFrameRate(5);//设置预览的时候以每秒五帧进行显示... param.setPictureFormat(PixelFormat.JPEG);//设置图片的格式为JPEG... param.set("jpeg-quality", 80);//设置图片的质量... try { Camera1.this.camera.setPreviewDisplay(Camera1.this.surfaceHolder);//设置我们预览时的SurfaceHolder... } catch (IOException e) { e.printStackTrace(); } Camera1.this.camera.startPreview();//开始预览... Camera1.this.previewrunning = true; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } @Override public void onClick(View v) { ActivityCompat.requestPermissions(Camera1.this, new String[]{android .Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case 1: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //创建文件夹 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // TODO Auto-generated method stub if (Camera1.this.camera != null) { Camera1.this.camera.autoFocus(new Camera.AutoFocusCallback() {//这里就是触发按钮来完成事件..这里是自动聚焦函数..内部需要实现三种方法.. @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { Camera1.this.camera.takePicture(null, null, jpeg); } } private Camera.PictureCallback jpeg = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);//把图片转化成字节数据... String filename = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "CameraPhoto" ; File file = new File(filename); if (!file.exists()) { file.mkdirs(); } try { FileOutputStream buf = new FileOutputStream(filename+File.separator+"picture.jpg"); bmp.compress(Bitmap.CompressFormat.JPEG, 100, buf);// buf.flush();// buf.close(); Intent intent=new Intent(Camera1.this,PhotoActivity.class); intent.putExtra("path",filename+File.separator+"picture.jpg"); startActivity(intent); } catch (Exception e) { e.printStackTrace(); } } }; }); } } break; } } }}
Layout.xml代码
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.myapplication.Camera1" tools:layout_editor_absoluteY="81dp" tools:layout_editor_absoluteX="0dp"> <Button android:id="@+id/TakePhoto" android:layout_width="0dp" android:layout_height="48dp" android:text="拍照" android:layout_marginStart="3dp" tools:layout_constraintRight_creator="1" tools:layout_constraintBottom_creator="1" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginEnd="3dp" app:layout_constraintRight_toRightOf="parent" tools:layout_constraintLeft_creator="1" android:layout_marginBottom="2dp" app:layout_constraintLeft_toLeftOf="parent" android:layout_marginLeft="3dp" android:layout_marginRight="3dp" /> <SurfaceView android:id="@+id/surfaceView" android:layout_width="0dp" android:layout_height="0dp" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintBottom_creator="1" app:layout_constraintBottom_toTopOf="@+id/TakePhoto" android:layout_marginStart="1dp" android:layout_marginEnd="1dp" app:layout_constraintRight_toRightOf="parent" android:layout_marginTop="1dp" tools:layout_constraintLeft_creator="1" android:layout_marginBottom="12dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginLeft="1dp" android:layout_marginRight="1dp" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintVertical_bias="0.0" /></android.support.constraint.ConstraintLayout>
附上一张图片
2.照片查看
实现里拍照,接下来就是照片查看了。先附上一个图片。
最上面显示图片的路径
然后是图片
再就是button,分别代表删除照片,返回上一步拍照界面,以及进行下一步功能,这里不涉及。
- 这个页面执行的前提是照片能够传过来。
在照相机制作中有段这样的代码Intent(Camera1.this,PhotoActivity.class);//从Camera1这个类跳到PhotoActivity类中,也就是照片查看的那个类中。当然是需要在startActivity(intent)后才可以做到。
intent.putExtra("path",filename+File.separator+"picture.jpg");//这里我们定义一个变量叫做path,其中path是等于filename+File.separator+"picture.jpg";
startActivity(intent);
在照片查看中就要接收这个path。
String path = getIntent().getStringExtra("path");
2.显示路径
tv_path.setText(path);//tv_path对应layout中的那个TextView.
3.图片显示
try { FileInputStream file = new FileInputStream(path); Bitmap bitmap = BitmapFactory.decodeStream(file); // 矩阵 Matrix matrix = new Matrix(); matrix.setRotate(90); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); iv_photo.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } }
4.删除
File file1 = new File(tv_path.getText().toString()); if(file1.exists()) { file1.delete(); Toast toast = Toast.makeText(PhotoActivity.this, "删除成功!", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); tv_path.setText("文件已删除!请点击上一步重新拍照!"); } else { Toast toast = Toast.makeText(PhotoActivity.this, "文件已删除!请点击上一步重新拍照!", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); }
5.回到上一步拍照的界面
Intent i=new Intent(PhotoActivity.this,Camera1.class); startActivity(i);
PS:从一个Activity跳到另外一个Activity还需要在Manifest中添加相应Activity事件。并且如果每个Activity中都是
<category android:name="android.intent.category.LAUNCHER" />
运行时,就会下载多个与App相同图片的应用。为了避免这个,我们可以在之后创建的Activity中换成
<category android:name="android.intent.category.DEFAULT" />
最后附上完整代码
Activity代码
package com.example.myapplication;/** * Created by 邓磊 on 2017/8/1. */import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.os.Bundle;import android.view.Gravity;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;public class PhotoActivity extends Activity implements View.OnClickListener { private TextView tv_path=null; private ImageView iv_photo=null; private Button next=null; private Button delete=null; private Button previous=null; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_photo); String path = getIntent().getStringExtra("path"); tv_path = (TextView) findViewById(R.id.tv_path); next=(Button)findViewById(R.id.next); delete=(Button)findViewById(R.id.delete); previous=(Button)findViewById(R.id.previous); // 显示路径 tv_path.setText(path); iv_photo = (ImageView) findViewById(R.id.iv_photo); next.setOnClickListener(this); delete.setOnClickListener(this); previous.setOnClickListener(this); // 调整角度 try { FileInputStream file = new FileInputStream(path); Bitmap bitmap = BitmapFactory.decodeStream(file); // 矩阵 Matrix matrix = new Matrix(); matrix.setRotate(90); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); iv_photo.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } } @Override public void onClick(View v) { switch (v.getId()){ case R.id.delete: File file1 = new File(tv_path.getText().toString()); if(file1.exists()) { file1.delete(); Toast toast = Toast.makeText(PhotoActivity.this, "删除成功!", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); tv_path.setText("文件已删除!请点击上一步重新拍照!"); } else { Toast toast = Toast.makeText(PhotoActivity.this, "文件已删除!请点击上一步重新拍照!", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } break; case R.id.previous: Intent i=new Intent(PhotoActivity.this,Camera1.class); startActivity(i); break; case R.id.next: Intent j=new Intent(PhotoActivity.this,QRcode.class); startActivity(j); break; } }}
Layout.xml代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_path" android:gravity="center" android:layout_width="match_parent" android:layout_height="30dp" /> <ImageView android:id="@+id/iv_photo" android:layout_width="385dp" android:layout_height="347dp" /> <Button android:id="@+id/delete" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="删除" /> <Button android:id="@+id/previous" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="上一步" /> <Button android:id="@+id/next" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="下一步" /></LinearLayout>
- Android 简单相机和照片查看器的制作
- 制作一个简单的照片查看器(支持缩放手势)
- android读取相册照片和相机照片
- 一个简单的window照片查看器
- Android调用系统相机照片和裁剪
- 简单的照片查看浏览
- android 调用相机 照片旋转的解决方案
- 关于android调用相机及拍照的存储和照片处理功能的全面小案例
- 关于android调用相机及拍照的存储和照片处理功能的全面小案例
- 简单制作漂亮的照片拼贴文字效果
- android调用相机及拍照的存储和照片处理功能
- 取原图旋转角度(IOS和Android相机拍的照片) 自动旋转
- SurfaceView surface SurfaceHolder制作简单的相机
- Android 打开相机和相册,适配(仅限单选照片)
- android---调用相机,捕获照片
- Android调用系统的相机保证照片的质量
- ios调用相机和照片
- Android使用相机获取照片并显示的代码
- hbase和es在搜索场景的应用
- 04Ext js学习之第一个Ext js程序
- 简单易接入的Zookeeper
- 比特币中交易延展性问题
- Nginx配置文件解析
- Android 简单相机和照片查看器的制作
- 在应用层调用OKhttp进行数据请求,更新View
- java匿名类
- ssm 之Struts 基础 (action)
- PLSQL修改表记录的语句
- [Paper 资源帖]CVPR 2017中有关GAN的Paper
- bzoj 1821: [JSOI2010]Group 部落划分
- 高效学习Hadoop生态的路线图、、、
- var hoisting