最近看到别人自定义的相机,自己也尝试写了一个。
功能 :完成简单的预览,拍照,回传,显示。
首先用到的控件 :button ,surfaceView, imagview 其中button为拍照按钮,surfaceView为画面,最后将获取的照片显示在iamgeview上
该篇比较简单,没有什么坑,唯一注意的是权限问题
<uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
前置和后置摄像头的选择 ,返回值不为-1,就是获取到了摄像头的id ,下面为获取方式。然后在预览页面获取camera的是时候当作参数即可(mCamera=Camera.open(cameraId));
public class MyCameraUtil { /** * 拿到前置摄像头id */ public static int findFrontCamera() { int cameraId = -1; int numberCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberCameras; i++) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { cameraId = i; break; } } return cameraId; } /** * 拿到后置摄像头id */ public static int findBackCamera() { int cameraId = -1; int numberCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberCameras; i++) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { cameraId = i; break; } } return cameraId; } }
mainActivity: 简单的跳转,显示
import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private static final int REQUEST_CAMERA_CODE_TEACHER=8001; private ImageView ima; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ima=(ImageView)findViewById(R.id.ima); } /** * 点击拍照 * @param view */ public void takePhoto(View view){ getPerssiom(); } /** * android6.0 申请拍照权限 */ private void getPerssiom(){ if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { gotoTake(); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE }, REQUEST_CAMERA_CODE_TEACHER); } } /** * 跳转至自定义的拍照页面 */ private void gotoTake(){ Intent intent =new Intent(MainActivity.this,CuptrueActivity.class); startActivityForResult(intent ,1); } /** * 拍照完成之后拿到路径设置imageview * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode==RESULT_OK){ if(requestCode==1){ String path = data.getStringExtra("picPath"); Bitmap bitmap = BitmapFactory.decodeFile(path); Matrix matrix=new Matrix(); matrix.setRotate(90); //由于拍照时旋转了90度。这里通矩阵旋转回来。 Bitmap bit= bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true); ima.setImageBitmap(bit); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_CAMERA_CODE_TEACHER: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults.length > 1 && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED) { gotoTake(); } else { Toast.makeText(MainActivity.this, "获取权限失败", Toast.LENGTH_SHORT).show(); } break; default: break; } } }
cuptureActiviy: 主要实现拍照的类
import android.app.Activity; import android.content.Intent; import android.graphics.ImageFormat; import android.hardware.Camera; import android.media.MediaFormat; import android.os.Bundle; import android.os.Environment; import android.os.PersistableBundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Toast; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; /** * Created by Administrator on 2017/1/4 0004. */ public class CuptrueActivity extends Activity implements SurfaceHolder.Callback { Camera mCamera; private SurfaceView surfaceView; private SurfaceHolder mHolder; private Camera.PictureCallback pictureCallBack =new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] bytes, Camera camera) { //bytes 即是拍照回来的内容,将内容写入本地即可 File file=new File(Environment.getExternalStorageDirectory().getPath() + "/test2.jpg"); if (file.exists()) { file.delete(); } try { FileOutputStream fo=new FileOutputStream(file); fo.write(bytes); fo.close(); Toast.makeText(CuptrueActivity.this,"已保存图片",Toast.LENGTH_SHORT).show(); Intent intent =new Intent(CuptrueActivity.this,MainActivity.class); //完成拍照,回到mainActivity,并将图片的路径回传 intent.putExtra("picPath",Environment.getExternalStorageDirectory().getPath() + "/test2.jpg"); setResult(RESULT_OK,intent); finish(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_cupture); surfaceView= (SurfaceView) findViewById(R.id.priview); mHolder= surfaceView.getHolder(); mHolder.addCallback(this); } public void take(View view){ //点击拍照的方法。 Camera.Parameters parameters =mCamera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean b, Camera camera) { if(b){ //如果焦点获取成功,拍照 mCamera.takePicture(null,null,pictureCallBack); //pictureCallBack 为拍照的回掉。 } } }); } @Override protected void onResume() { super.onResume(); if(mCamera==null){ mCamera= getCamera(); } if(mCamera!=null&&mHolder!=null){ startPriview(mCamera ,mHolder); } } @Override protected void onPause() { super.onPause(); releseCamera(); } private Camera getCamera(){ Camera camera; try{ camera=Camera.open(); }catch (Exception ex){ camera=null; } return camera; } /** * 将相机与SurfaceView 绑定。将拍到的画面显示到页面上。 * @param camera * @param holder */ private void startPriview(Camera camera, SurfaceHolder holder){ try { Camera.Parameters parameters =camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //自动获取焦点,(大部分手机都有这个功能)。 这个在预览页面好像不能用,所以用了下面的方式,在视觉效果上可以达到想要的效果 List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } camera.setPreviewDisplay(holder); //将相机与SurfaceView 绑定。 camera.setDisplayOrientation(90); //自定义相机是横屏的,不满足需求,所以旋转了90度。 camera.startPreview(); //开始显示画面 } catch (IOException e) { e.printStackTrace(); } } private void releseCamera(){ //释放资源 if(mCamera!=null){ mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera=null; } } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { if(mCamera!=null){ startPriview(mCamera ,mHolder); } } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { if(mCamera!=null){ mCamera.stopPreview(); startPriview(mCamera ,mHolder); } } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { releseCamera(); } }
main_layout:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.administrator.customcamera.MainActivity"> <Button android:id="@+id/but" android:onClick="takePhoto" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" /> <ImageView android:id="@+id/ima" android:layout_width="200dp" android:layout_below="@id/but" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:layout_height="200dp" /> </RelativeLayout>
capture_layout:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:background="#00000000" android:layout_height="match_parent"> <SurfaceView android:id="@+id/priview" android:layout_above="@+id/but_takephoto" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/but_takephoto" android:layout_width="wrap_content" android:layout_height="40dp" android:onClick="take" android:layout_centerHorizontal="true" android:text="拍照" android:layout_alignParentBottom="true"/> </RelativeLayout>