当前位置: 首页 > wzjs >正文

长沙产品网站建设阜新市项目建设网站

长沙产品网站建设,阜新市项目建设网站,承接电商网站建设,网站建设的利润率多少相机功能 安卓中的相机调用功能也经历了很多的方案升级,目前可选的官方方案是CameraX、Camera2、Camera(废弃),还有一些第三方免费或者是付费的相机库。对于大多数开发者,建议使用 CameraX。 CameraX CameraX 是 An…

相机功能

安卓中的相机调用功能也经历了很多的方案升级,目前可选的官方方案是CameraX、Camera2、Camera(废弃),还有一些第三方免费或者是付费的相机库。对于大多数开发者,建议使用 CameraX。

CameraX

CameraX 是 Android Jetpack 库的一部分,旨在简化相机应用的开发。它构建在 Camera2 API 之上,为开发者提供了更简洁的接口,相比于Camera和Camera2,有更好的设备兼容性。

  • 简单易用:相比 Camera2,CameraX 简化了相机操作,提供了更直观的 API,可以更快实现常见的相机功能。
  • 向后兼容性:CameraX 支持 Android 5.0 (API 21) 及以上版本,解决了 Camera2 在一些设备上的兼容性问题。
  • 生命周期感知:CameraX 会自动处理生命周期问题,例如当用户切换到后台时停止相机,回到前台时重新启动。
  • 内置扩展:CameraX 提供了诸如 HDR、夜间模式、美颜等功能,支持基于不同设备硬件的特性自动调整。不过这个需要看手机型号,很多手机并不支持。

CameraX拍照

  1. 项目依赖配置

在 build.gradle 文件中添加 CameraX 相关依赖:

def camerax_version = "1.2.0-alpha04" implementation "androidx.camera:camera-core:$camerax_version"//核心库 implementation "androidx.camera:camera-camera2:$camerax_version"//基于 Camera2 的实现模块 implementation "androidx.camera:camera-lifecycle:$camerax_version"//自动管理相机的生命周期 implementation "androidx.camera:camera-view:1.0.0-alpha31"//显示相机预览的 UI 组件 implementation "androidx.camera:camera-extensions:1.0.0-alpha31"//额外的高级相机功能如 HDR 和美颜

  1. 权限配置(AndroidManifest.xml)

运行相机需要对相机权限做出声明:

<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false" />

android:required="false":这意味着相机功能并不是应用的必需条件。如果设备没有相机,应用仍然可以安装和运行。如果是true,而设备本身没有相机,那应用就无法正常运行。

  1. 布局文件(activity_main.xml)

<!-- CameraX 预览控件 --> <androidx.camera.view.PreviewView android:id="@+id/previewView" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/captureButton" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <!-- 拍照按钮 --> <Button android:id="@+id/captureButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" app:layout_constraintTop_toBottomOf="@+id/previewView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" />

  1. Activity中

package com.example.cameraxdemo; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.camera.core.Camera; import androidx.camera.core.CameraSelector; import androidx.camera.core.ImageCapture; import androidx.camera.core.ImageCaptureException; import androidx.camera.core.Preview; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.view.PreviewView; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_PERMISSIONS = 10; private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA}; private PreviewView previewView; private ImageCapture imageCapture; private ExecutorService cameraExecutor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); previewView = findViewById(R.id.previewView); Button captureButton = findViewById(R.id.captureButton); // 请求相机权限,如果有权限直接启动相机 if (allPermissionsGranted()) { startCamera(); } else { ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS); } // 点击拍照按钮时执行拍照 captureButton.setOnClickListener(view -> takePhoto()); cameraExecutor = Executors.newSingleThreadExecutor(); } // 初始化相机 private void startCamera() { ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { try { // 获取 CameraProvider ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); // 创建预览 Preview preview = new Preview.Builder().build(); // 创建 ImageCapture,用于拍照 imageCapture = new ImageCapture.Builder().build(); // 选择后置摄像头 CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; // 将预览与 PreviewView 绑定 preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 绑定预览和 ImageCapture 到相机生命周期 cameraProvider.unbindAll(); Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture); } catch (ExecutionException | InterruptedException e) { Log.e("CameraXDemo", "Error starting camera: ", e); } }, ContextCompat.getMainExecutor(this)); } // 拍照逻辑 private void takePhoto() { if (imageCapture == null) { return; } // 创建保存文件 File photoFile = new File(getExternalFilesDir(null), System.currentTimeMillis() + ".jpg"); // 设置拍照输出选项 ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build(); // 执行拍照 imageCapture.takePicture(outputFileOptions, cameraExecutor, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo saved: " + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show()); } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e("CameraXDemo", "Photo capture failed: " + exception.getMessage(), exception); } }); } // 检查是否已经获得所有权限 private boolean allPermissionsGranted() { for (String permission : REQUIRED_PERMISSIONS) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } // 权限请求结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_CODE_PERMISSIONS) { if (allPermissionsGranted()) { startCamera(); } else { Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show(); finish(); } } } @Override protected void onDestroy() { super.onDestroy(); cameraExecutor.shutdown(); } }

使用MediaStore,遵循分区存储:

// 创建 ContentValues ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis() + ".jpg"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/CameraXDemo"); // 设置输出选项 ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build(); // 拍照 imageCapture.takePicture(outputFileOptions, cameraExecutor, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Uri savedUri = outputFileResults.getSavedUri(); if (savedUri != null) { runOnUiThread(() -> Toast.makeText(CameraActivity.this, "Photo saved to MediaStore: " + savedUri, Toast.LENGTH_SHORT).show()); } else { Log.e(TAG, "Image not saved properly."); } } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e(TAG, "Photo capture failed: " + exception.getMessage(), exception); } });

切换前后置摄像头

主要思路是重新绑定摄像头,在重新绑定之前切换前后摄像头参数即可:

public class MainActivity extends AppCompatActivity { private PreviewView previewView; private ImageCapture imageCapture; private ProcessCameraProvider cameraProvider; private CameraSelector cameraSelector; private boolean isFrontCamera = false; // 默认后置摄像头 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); previewView = findViewById(R.id.previewView); // 启动相机 startCamera(); // 切换摄像头按钮点击事件 findViewById(R.id.switchCameraButton).setOnClickListener(v -> { isFrontCamera = !isFrontCamera; switchCamera(); }); } private void startCamera() { // 获取 CameraProvider ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { try { cameraProvider = cameraProviderFuture.get(); // 默认使用后置摄像头 cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; bindCameraUseCases(); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } }, ContextCompat.getMainExecutor(this)); } private void bindCameraUseCases() { // 创建预览 Preview preview = new Preview.Builder().build(); // 将 Preview 连接到 PreviewView preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 拍照设置 imageCapture = new ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build(); // 解绑之前的所有用例 cameraProvider.unbindAll(); // 绑定预览和拍照功能到相机 cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture); } private void switchCamera() { // 切换前后置摄像头 if (isFrontCamera) { cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA; } else { cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; } // 重新绑定摄像头 bindCameraUseCases(); } // 拍照方法 private void takePicture() { if (imageCapture != null) { ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "my_image_" + System.currentTimeMillis() + ".jpg"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build(); imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) { Uri savedUri = outputFileResults.getSavedUri(); Log.d("CameraXApp", "Image saved: " + savedUri); } @Override public void onError(ImageCaptureException exception) { Log.e("CameraXApp", "Error saving image: " + exception.getMessage()); } }); } } }

CameraX视频拍摄

  1. 项目依赖配置

除了CameraX的基础依赖库,还需要新增下面的库:

implementation "androidx.camera:camera-video:$camerax_version" // 视频录制相关库

  1. 权限配置

录制视频,除了需要获取相机权限,还需要额外添加录音权限

<uses-permission android:name="android.permission.RECORD_AUDIO" />

  1. Activity中

public class VideoRecordActivity extends AppCompatActivity { private static final String TAG = "VideoRecordActivity"; private PreviewView previewView;// 预览摄像头捕获内容的视图 private ExecutorService cameraExecutor;// 用于处理相机操作的后台线程 private boolean isRecording; // 记录否正在录制的状态 private VideoCapture<Recorder> videoCapture; //捕获视频的核心组件 // private Recording recording; private ProcessCameraProvider cameraProvider;// 相机的生命周期管理组件 private CameraSelector cameraSelector;// 前置或后置摄像头 private Recording recording;//当前正在进行的录制实例 private ImageView ivRecord; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_record); previewView = findViewById(R.id.preview); //拍照 ivRecord = findViewById(R.id.tv_take); ivRecord.setOnClickListener(view -> { // 如果当前正在录制,点击按钮停止录制,否则就是开始录制 if (isRecording) { stopRecording(); } else { startRecording(); } }); // 创建单线程后台线程池 cameraExecutor = Executors.newSingleThreadExecutor(); startCamera(); requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 11); } // 启动相机预览 private void startCamera() { ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); // 异步获取摄像头的命周期管理器实例 cameraProviderFuture.addListener(() -> { try { // 获取摄像头生命周期管理器实例 cameraProvider = cameraProviderFuture.get(); // 创建预览实例 Preview preview = new Preview.Builder().build(); // 将预览内容绑定到 PreviewView 上 preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 视频录制用例 Recorder recorder = new Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.HD)) // 设置录制质量为 HD .build(); // 创建 VideoCapture 用例,这个一个获取视频的核心组件 videoCapture = VideoCapture.withOutput(recorder); // 默认使用后置摄像头 cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; //解绑所有之前的摄像头用例 cameraProvider.unbindAll(); // 将预览和视频录制绑定到生命周期 cameraProvider.bindToLifecycle(VideoRecordActivity.this, cameraSelector, preview, videoCapture); } catch (ExecutionException | InterruptedException e) { Log.e(TAG, "Error starting camera", e); } }, ContextCompat.getMainExecutor(this));// 在主线程执行 } private void startRecording() { if (isRecording) { Toast.makeText(this, "Recording is already in progress", Toast.LENGTH_SHORT).show(); return; } // 创建保存视频的 ContentValues,指定文件名和文件类型 ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "video_" + System.currentTimeMillis()); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); // 使用 MediaStoreOutputOptions 指定输出位置 MediaStoreOutputOptions options = new MediaStoreOutputOptions.Builder(getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI) .setContentValues(contentValues).build(); // 准备录制前检查录音权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "请先获取录音权限", Toast.LENGTH_SHORT).show(); return; } // 准备录制视频,并启用音频录制 PendingRecording pendingRecording = videoCapture.getOutput() .prepareRecording(VideoRecordActivity.this, options) .withAudioEnabled(); // 如果需要音频录制,调用该方法 // 启动录制,并且设定录制回调 //回调中的videoRecordEvent会有下面几种状态: //VideoRecordEvent.Start:录制开始。 //VideoRecordEvent.Pause:录制暂停。 //VideoRecordEvent.Resume:录制恢复。 //VideoRecordEvent.Finalize:录制完成(停止或失败)。 //VideoRecordEvent.Status:录制状态更新(持续获取统计信息)。 recording = pendingRecording.start(ContextCompat.getMainExecutor(this), videoRecordEvent -> { Log.d(TAG, "Recording videoRecordEvent " + videoRecordEvent); Log.d(TAG, "Recording videoRecordEvent getRecordingStats" + videoRecordEvent.getRecordingStats()); if (videoRecordEvent instanceof VideoRecordEvent.Start) { Log.d(TAG, "Recording started"); isRecording = true; refreshUI(videoRecordEvent); } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) { Log.d(TAG, "Recording finalized"); Toast.makeText(this, "已保存", Toast.LENGTH_SHORT).show(); isRecording = false; refreshUI(videoRecordEvent); } }); } private void stopRecording() { if (recording != null && isRecording) { recording.stop(); // 停止录制 recording = null; } } //更新UI private void refreshUI(VideoRecordEvent videoRecordEvent) { if (videoRecordEvent instanceof VideoRecordEvent.Start) { //开始录制,把相关的ui换成录制的效果 ivRecord.setImageResource(R.mipmap.icon_stop_record); } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) { //结束录制 ivRecord.setImageResource(R.mipmap.icon_record); }else{ //这里可以自行扩展其他的状态 } } @Override protected void onDestroy() { super.onDestroy(); cameraExecutor.shutdown(); } }


文章转载自:

http://kHjW7iYg.gwcjq.cn
http://aigBcmCH.gwcjq.cn
http://P1c7GZt6.gwcjq.cn
http://0BtHdQT8.gwcjq.cn
http://95k2Rz2B.gwcjq.cn
http://doTG27P9.gwcjq.cn
http://JmirAdXB.gwcjq.cn
http://6Iok5RGB.gwcjq.cn
http://2WvX6xTA.gwcjq.cn
http://fRsy6Gw1.gwcjq.cn
http://nG90oloI.gwcjq.cn
http://yMSpePQw.gwcjq.cn
http://NBgiW7e3.gwcjq.cn
http://Jtk6RZbY.gwcjq.cn
http://xnbSZy61.gwcjq.cn
http://WSPCU5Zx.gwcjq.cn
http://MGeJrPJV.gwcjq.cn
http://OzYb9Ui1.gwcjq.cn
http://PnsIdztH.gwcjq.cn
http://9140VrY2.gwcjq.cn
http://iQmuxAXZ.gwcjq.cn
http://NmRO3Tmh.gwcjq.cn
http://oPDb5pS9.gwcjq.cn
http://cPz5lBGO.gwcjq.cn
http://sCbz4tui.gwcjq.cn
http://D9Yoznom.gwcjq.cn
http://ATWW17qt.gwcjq.cn
http://5j2aI0lE.gwcjq.cn
http://syYPMvEG.gwcjq.cn
http://Jr5kdIxJ.gwcjq.cn
http://www.dtcms.com/wzjs/751920.html

相关文章:

  • c语言和c 哪个做网站好沈阳做网站 熊掌号
  • 给图像做标注的网站福州网站设计十年乐云seo
  • 哈尔滨网站网站建设专业建站方案
  • 网页开发和网站开发一样吗百度百科网站怎么做
  • 网站免费推广的方法专业的网站制作公司
  • 简单的网站开发的软件wordpress 部分图打不开
  • 丰都县网站灰色词seo排名
  • 网站建设私活软装设计ppt
  • 国内做网站比较好的公司页面设计属于什么专业
  • 中山制作网站的公司畅销营销型网站建设电话
  • wordpress做网站优点龙岗网站建设培训
  • 建设电子商务网站论文2023年招标公告
  • 山东网站建设网济南品牌网站制作便宜
  • 个人网站可以做什么小程序是怎么赚钱的
  • 做百度推广网站排名怎么开自己的网站
  • 大学生网站建设实训报告在线购物系统的分析与设计
  • 关于网站开发的商业计划书长沙微信网站
  • 网站前端建设需要学会什么wordpress 商品导航菜单
  • 化隆县公司网站建设电子商务网站购物车怎么做
  • 番禺网站建设哪家好淄博市建设工程质量协会网站
  • 安卓手机 做网站中小企业网站模板
  • 网站手机端跳转页面模板做外贸女装有哪些网站有哪些
  • 1网站建设公司网站挂服务器后图片不显示
  • 百度免费网站空间云南建站推广
  • 泰州哪里做网站怀来县网站建设
  • 椒江区建设局网站无锡网站建设工作室
  • 淘宝客导购网站模板html在线记账网站模板
  • 移动互联网网站开发技术网站制作需要多长时间
  • 专业的led网站建设网站如何做原创
  • 企业网站建设哪家专业深圳市场调研公司