这两天研究了一下 如何自定义相机:
包含如下 :
创建相机
创建surfaceview
关联相机和surfaceview
调整相机的显示效果
自定义相机预览界面
在这里直接上源码,源码内包含注释:
基本实现方式已经说得很明白了,具体细节请根据需求,进行相关更改:
主界面:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context="com.lgoutech.mycamera.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StartCamera1"
android:onClick="startCamera1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StartCamera2"
android:onClick="startCamera2"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CustomCamera"
android:onClick="customCamera"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/iv"
/>
</LinearLayout>
MainActivity:
public class MainActivity extends AppCompatActivity {
/* 相机请求码 */
private static final int REQUEST_CAMERA = 0;
private static int REQ_1=1;
private static int REQ_2=2;
private ImageView mImageView;
//图片 路径
private String mFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 第一次申请,就直接申请
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA);
mImageView = findViewById(R.id.iv);
//获取sdk 目录
mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath + "/" + "temp.png";
}
public void startCamera1(View view) {
//隐式 调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
public void startCamera2(View view) {
//隐式 调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//uri指定为我们创建的路径
Uri photoUri = Uri.fromFile(new File(mFilePath));
//通过 output 将系统存储路径放在我创建的路径当中
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent,REQ_2);
}
public void customCamera(View view) {
Intent intent = new Intent(this, CustomCameraActivity.class);
startActivity(intent);
}
//处理返回结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//返回结果成功
if (resultCode == RESULT_OK) {
//如果返回结果是我们定义的code 去处理
if (requestCode == REQ_1) {
//返回结果是缩略图 不清楚
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
mImageView.setImageBitmap(bitmap);
} else if (requestCode == REQ_2) {
//通过fis将路径转换为图片
FileInputStream fis = null;
try {
fis = new FileInputStream(mFilePath);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
mImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
CustomeCameraActivity:
public class CustomCameraActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头
private Camera mCamera;
private SurfaceView mPreView;
private SurfaceHolder mHolder;
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File tempFile = new File("/sdcard/temp.png");
try {
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(data);
fos.close();
Intent intent = new Intent(CustomCameraActivity.this,ResultActivity.class);
intent.putExtra("picPath", tempFile.getAbsolutePath());
startActivity(intent);
CustomCameraActivity.this.finish();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_camera);
mPreView = findViewById(R.id.preview);
mHolder = mPreView.getHolder();
mHolder.addCallback(this);
mPreView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//不进行任何操作 ,只是自动对焦
mCamera.autoFocus(null);
}
});
}
//切换前后摄像头
public void upGoBack(View view) {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
if (cameraPosition == 1) {
//现在是后置,变更为前置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
releaseCamera();
mCamera = Camera.open(i);//打开当前选中的摄像头
setStartPreview(mCamera,mHolder);
cameraPosition = 0;
break;
}
} else {
//现在是前置, 变更为后置
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
releaseCamera();
mCamera = Camera.open(i);//打开当前选中的摄像头
setStartPreview(mCamera,mHolder);
cameraPosition = 1;
break;
}
}
}
}
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);
// parameters.setRotation(180);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
mCamera.takePicture(null,null,mPictureCallback);
}
});
}
@Override
protected void onResume() {
super.onResume();
if (mCamera == null) {
mCamera = getCamera();
if(mHolder!=null){
setStartPreview(mCamera, mHolder);
}
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
/**
* 获取 Camera对象
* 需要导入的包 hardware
* @return
*/
private Camera getCamera(){
Camera camera;
try {
camera=Camera.open();
} catch (Exception e) {
camera = null;
e.printStackTrace();
}
return camera;
}
/**
* 开始 预览 相机内容
*/
private void setStartPreview(Camera camera,SurfaceHolder holder){
try {
camera.setPreviewDisplay(holder);
//将系统camera预览角度 进行调整 横平转换为竖屏
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 释放相机资源
*/
private void releaseCamera(){
if (mCamera != null) {
//预览回调 置空
mCamera.setPreviewCallback(null);
//停止预览
mCamera.stopPreview();
//释放占有资源
mCamera.release();
mCamera = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//开始时 surcafeview 与相机绑定
setStartPreview(mCamera, mHolder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.stopPreview();
setStartPreview(mCamera, mHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
}
ResultActivity:
public class ResultActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
String path = getIntent().getStringExtra("picPath");
ImageView imageView = findViewById(R.id.pic);
FileInputStream fis = null;
try {
fis = new FileInputStream(path);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
//矩阵
Matrix matrix = new Matrix();
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,true);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.setImageBitmap(BitmapFactory.decodeFile(path));
}
}
注意事项:
因为我的targetSdkVersion 为26
所以需要动态获取权限,在MainActivity中我已经 简单加上了申请权限,没有任何问题,可直接使用的。。。