本文主要是介绍使用摄像头预览和拍照(Camera1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
参考文章:
https://blog.csdn.net/u011418943/article/details/107256406
https://blog.csdn.net/xiaodongvtion/article/details/110951754
Camera1的类android.hardware.Camera。Camera类常用的方法:
方法 | 描述 |
getParameters() | 获取摄像头参数 |
setParameters() | 设置摄像头参数 |
setPreviewDisplay() | 为摄像头指定一个显示预览画面的SurfaceView |
open() | 打开摄像头 |
startPreview() | 开始预览 |
stopPreview() | 停止预览 |
release() | 释放摄像头资源 |
takePicture() | 进行拍照 |
1 代码
CameraPreview:
GitHub - hanyuhang-hz/android-demos
MainActivity.java
public class MainActivity extends Activity {public final static String TAG = "CameraPreview";private Camera camera;private boolean isPreview = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.CAMERA}, 1);}if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}// 设置全屏显示getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 判断手机是否安装SD卡if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {Toast.makeText(this, "请安装SD卡!", Toast.LENGTH_SHORT).show();}SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);final SurfaceHolder surfaceHolder = surfaceView.getHolder();// 设置该SurfaceHolder自己不维护缓冲surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);ImageButton preview = (ImageButton) findViewById(R.id.preview);preview.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 如果相机为非预览模式,则打开相机if (!isPreview) {camera = Camera.open();isPreview = true;}try {// 设置用于显示预览的SurfaceViewcamera.setPreviewDisplay(surfaceHolder);Camera.Parameters parameters = camera.getParameters();// 测试Camera.Parameters// (1)setPictureFormat======================================// PixelFormat.JPEG:jpeg// parameters.setPictureFormat(PixelFormat.JPEG); // 指定图片为JPEG图片// parameters.set("jpeg-quality", 80); // 设置图片的质量// PixelFormat.YCbCr_420_SP:NV21,等价于ImageFormat.NV21parameters.setPictureFormat(PixelFormat.YCbCr_420_SP);// (2)setWhiteBalance======================================// autoString whiteBalance = parameters.getWhiteBalance();Log.d(TAG, "whiteBalance:" + whiteBalance);// WHITE_BALANCE_INCANDESCENT:偏蓝// WHITE_BALANCE_FLUORESCENT:偏淡蓝// WHITE_BALANCE_WARM_FLUORESCENT:偏淡蓝// WHITE_BALANCE_DAYLIGHT:日光,正常// WHITE_BALANCE_CLOUDY_DAYLIGHT:阴天,偏黄// WHITE_BALANCE_TWILIGHT:暮光,偏黄// WHITE_BALANCE_SHADE:偏黄parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);whiteBalance = parameters.getWhiteBalance();Log.d(TAG, "whiteBalance:" + whiteBalance);// (3)setExposureCompensation======================================曝光补偿int minEx = parameters.getMinExposureCompensation();int maxEx = parameters.getMaxExposureCompensation();float stepEx = parameters.getExposureCompensationStep();Log.d(TAG, "minEx:" + minEx + " maxEx:" + maxEx + " stepEx:" + stepEx);parameters.setExposureCompensation(6);// (4)setAutoExposureLock======================================boolean isAELS = parameters.isAutoExposureLockSupported();Log.d(TAG, "isAES:" + isAELS);boolean getAELS = parameters.getAutoExposureLock();Log.d(TAG, "getAES:" + getAELS);parameters.setAutoExposureLock(false);getAELS = parameters.getAutoExposureLock();Log.d(TAG, "getAES:" + getAELS);// (5)setAutoWhiteBalanceLock======================================boolean isAWBLS = parameters.isAutoWhiteBalanceLockSupported();Log.d(TAG, "isAWBLS:" + isAWBLS);boolean getAWBL = parameters.getAutoWhiteBalanceLock();Log.d(TAG, "getAWBL:" + getAWBL);parameters.setAutoWhiteBalanceLock(false);getAWBL = parameters.getAutoWhiteBalanceLock();Log.d(TAG, "getAWBL:" + getAWBL);// (5)setFocusMode======================================String fm = parameters.getFocusMode();Log.d(TAG, "fm:" + fm);// FOCUS_MODE_AUTO:聚焦// FOCUS_MODE_INFINITY:不聚焦// FOCUS_MODE_MACRO:聚焦// FOCUS_MODE_CONTINUOUS_VIDEO:跟随预览的物体远近自动聚焦,afcb返回fail// FOCUS_MODE_CONTINUOUS_PICTURE:跟随预览的物体远近自动聚焦,afcb返回failparameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);fm = parameters.getFocusMode();Log.d(TAG, "fm:" + fm);camera.setParameters(parameters);camera.startPreview();// AF:自动对焦camera.autoFocus(afcb);camera.setDisplayOrientation(90);} catch (IOException e) {e.printStackTrace();}}});ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto);takePicture.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (camera != null) {camera.takePicture(null, null, jpeg);}}});}final Camera.AutoFocusCallback afcb = new Camera.AutoFocusCallback() {@Overridepublic void onAutoFocus(boolean success, Camera camera) {if(success) {// success表示对焦成功Log.d(TAG, "afcb: success");//camera.setOneShotPreviewCallback(null);}else {// 未对焦成功Log.d(TAG, "afcb: fail");}}};// 照片回调函数,实现将照片保存到系统图库中final Camera.PictureCallback jpeg = new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// 根据拍照所得的数据创建位图final Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);camera.stopPreview();isPreview = false;Log.d(TAG, "Environment.getExternalStorageDirectory():" + Environment.getExternalStorageDirectory());//获取sd卡根目录File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/");if (!appDir.exists()) { // 如果该目录不存在就创建该目录appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);// 保存拍到的图片try {FileOutputStream fos = new FileOutputStream(file); // 创建一个文件输出流对象boolean ret = bm.compress(Bitmap.CompressFormat.JPEG, 100, fos); // 将图片内容压缩为JPEG格式输出到输出流对象中Log.d(TAG, "bm.compress ret:" + ret);fos.flush();fos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}//将照片插入到系统图库try {MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}// 最后通知图库更新MainActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse("file://" + "")));Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show();resetCamera();}};// 创建resetCamera()方法,实现重新预览功能private void resetCamera() {if (!isPreview) {camera.startPreview();isPreview = true;}}@Overrideprotected void onPause() {if (camera != null) {camera.stopPreview();camera.release();}super.onPause();}
}
查看手机是否安装SD卡:
adb shell mount
adb shell df -h
手机内部存储相册路径:/storage/emulated/0/DCIM/Camera/
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"tools:context=".MainActivity"><!--SurfaceView组件--><SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="match_parent" /><!--拍照按钮--><ImageButtonandroid:id="@+id/takephoto"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right|top"android:layout_marginTop="@dimen/margin_top"android:background="@color/btn_background"android:src="@drawable/camera" /><!--预览按钮--><ImageButtonandroid:id="@+id/preview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right|bottom"android:layout_marginBottom="@dimen/margin_bottom"android:background="@color/btn_background"android:src="@drawable/preview" /></FrameLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.hyh.camerapreview"><!-- 授予程序可以向SD卡中保存文件的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- 授予程序使用摄像头的权限 --><uses-permission android:name="android.permission.CAMERA"/><uses-feature android:name="android.hardware.camera.autofocus"/><uses-feature android:name="android.hardware.camera"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.CameraPreview"android:requestLegacyExternalStorage="true"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
2 遇到的问题
2.1 预览时图片拉伸
需要设置预览方向
camera.setDisplayOrientation(90);
2.2 拍照时不能保存相片
java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/1638007179710.jpg: open failed: ENOENT (No such file or directory)
android:requestLegacyExternalStorage="true"
原因是Android10弃用了管理分区外部储存
这篇关于使用摄像头预览和拍照(Camera1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!