一. 使用Camera的方式
- 调用系统相机
- 自定义相机
二. 调用系统相机
1.调用系统相机,并返回缩略图
public static final int REQUEST_CODE = 0x001;
private ImageView ivPic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivPic = findViewById(R.id.iv_pic);
}
public void invokeSystemCamera(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 1.使用到的Action
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { // data返回的是缩略图,防止数据过大导致内存溢出
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
if (data != null) {
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data"); // 2.获取缩略图
ivPic.setImageBitmap(bitmap);
}
}
}
2.调用系统相机,并返回原图
通过Uri来指定图片保存路径,这里需要做7.0兼容,否则会报错。(这里需要WRITE_EXTERNAL_STORAGE权限)
public static final int REQUEST_CODE2 = 0x002;
public static final int PERMISSION_REQUEST_CODE = 0x003;
private ImageView ivPic;
private String imagePath = Environment.getExternalStorageDirectory() + File.separator + "temp.jpg";
private File imageFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivPic = findViewById(R.id.iv_pic);
imageFile = new File(imagePath); // 1.设置图片保存路径
requestPermission(); // 要使用到WRITE_EXTERNAL_STORAGE权限
}
private void requestPermission() {
ArrayList<String> permissionList = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionList.size() > 0) {
String[] permissions = new String[permissionList.size()];
permissionList.toArray(permissions);
ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
public void invokeSystemCamera2(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { // 7.0以下系统使用文件的Uri
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
uri = Uri.fromFile(imageFile); // 7.0 使用此方式会报Caused by: android.os.FileUriExposedException
} else {
uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".authority", imageFile); // 使用FileProvider兼容7.0及以上版本
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); // 2.通过uri告诉系统图片保存路径,这里的uri需要做兼容
startActivityForResult(intent, REQUEST_CODE2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE2 && resultCode == RESULT_OK) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(imageFile); // 3.将图片文件转换为流
Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream); // 4.获取bitmap
ivPic.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
AndroidManifest的FileProvider配置
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.lgf.camera.demo.authority"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
res下xml的file_path配置:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="imagePath"
path="/" />
</paths>
三.自定义相机
这里用android.hardware.Camera类实现,关于Camera2和CameraView还未了解。
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
public class CameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
public static final int PERMISSION_REQUEST_CODE = 0x003;
private Camera mCamera;
private SurfaceView svCamera;
private SurfaceHolder mSurfaceHolder;
private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 处理图片数据
File file = new File(Environment.getExternalStorageDirectory(), "temp.png");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
svCamera = findViewById(R.id.sv_camera); // 1,获取SurfaceView对象
mSurfaceHolder = svCamera.getHolder();
mSurfaceHolder.addCallback(this); // 监听SurfaceView事件
svCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.autoFocus(null); // 点击SurfaceView对焦,但是不回调
}
});
requestPermission();
}
private void requestPermission() {
ArrayList<String> permissionList = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
permissionList.add(Manifest.permission.CAMERA);
}
if (permissionList.size() > 0) {
String[] permissions = new String[permissionList.size()];
permissionList.toArray(permissions);
ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
}
}
private void setStartPreview(Camera camera, SurfaceHolder surfaceHolder) {
try {
camera.setDisplayOrientation(90); // 设置预览方向,否则会横屏显示
camera.setPreviewDisplay(surfaceHolder); // 3.关联Camera和SurfaceView,设置显示在SurfaceHolder
camera.startPreview(); // 开始预览
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
startPreview();
}
@Override
protected void onPause() {
super.onPause();
releaseCamera(); // 释放Camera资源
}
private void startPreview() {
createCamera();
if (mSurfaceHolder != null) {
setStartPreview(mCamera, mSurfaceHolder);
}
}
private void createCamera() {
if (mCamera == null) {
mCamera = Camera.open(); // 2.创建Camera对象
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null); // 停止监听回调
mCamera.stopPreview(); // 停止预览
mCamera.release(); // 释放camera资源
mCamera = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) { // 界面获取焦点时,回调
Log.d("CameraActivity", "surfaceCreated");
setStartPreview(mCamera, mSurfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 界面获取焦点时或SurfaceView大小改变时,回调
Log.d("CameraActivity", "surfaceChanged");
mCamera.stopPreview();
setStartPreview(mCamera, mSurfaceHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) { // 界面失去焦点时,回调
Log.d("CameraActivity", "surfaceDestroyed");
releaseCamera();
}
/**
* 此方法为点击事件
* @param view
*/
public void capture(View view) {
// 设置参数
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG); // 设置图片格式
parameters.setPreviewSize(800, 400); // 设置图片大小
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// 对焦,并获取对焦结果
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) { // 对焦成功
mCamera.takePicture(null/*拍照时,会发出拍照的声音*/, null, pictureCallback);
}
}
});
}
}
**备注:**onResume、onPause、surfaceCreated、surfaceChanged、surfaceDestroyed生命周期
onResume->surfaceCreated->surfaceChanged->onPause->surfaceDestroyed